Installing Control Plane on Kubernetes

This page describes how to install control plane on a Kubernetes cluster.

Prerequisites

  • A running Kubernetes cluster
  • Installed Helm (3.8.0 or later)

Installation

1. Preparing an encryption key

PipeCD requires a key for encrypting sensitive data or signing JWT tokens while authenticating. You can use one of the following commands to generate an encryption key.

openssl rand 64 | base64 > encryption-key

# or
cat /dev/urandom | head -c64 | base64 > encryption-key

2. Preparing Control Plane configuration file and installing

Control Plane Architecture

The Control Plane of PipeCD is constructed by several components, as shown in the above graph (for more details please read Control Plane architecture overview docs). As mentioned in the graph, PipeCD’s data can be stored in one of the provided fully-managed or self-managed services. So you have to decide which kind of data store and file store you want to use and prepare a Control Plane configuration file suitable for that choice.

Using Firestore and GCS

PipeCD requires a GCS bucket and service account files to access Firestore and GCS service. Here is an example configuration file:

apiVersion: "pipecd.dev/v1beta1"
kind: ControlPlane
spec:
  stateKey: {RANDOM_STRING}
  datastore:
    type: FIRESTORE
    config:
      namespace: pipecd
      environment: dev
      project: {YOUR_GCP_PROJECT_NAME}
      # Must be a service account with "Cloud Datastore User" and "Cloud Datastore Index Admin" roles
      # since PipeCD needs them to create the needed Firestore composite indexes in the background.
      credentialsFile: /etc/pipecd-secret/firestore-service-account
  filestore:
    type: GCS
    config:
      bucket: {YOUR_BUCKET_NAME}
      # Must be a service account with "Storage Object Admin (roles/storage.objectAdmin)" role on the given bucket
      # since PipeCD needs to write file objects such as deployment log files to that bucket.
      credentialsFile: /etc/pipecd-secret/gcs-service-account

See Configuration reference for the full configuration.

After all, install the Control Plane as below:

helm upgrade -i pipecd oci://ghcr.io/pipe-cd/chart/pipecd --version v0.55.0 --namespace={NAMESPACE} \
  --set-file config.data=path-to-control-plane-configuration-file \
  --set-file secret.encryptionKey.data=path-to-encryption-key-file \
  --set-file secret.firestoreServiceAccount.data=path-to-service-account-file \
  --set-file secret.gcsServiceAccount.data=path-to-service-account-file

Currently, besides Firestore PipeCD supports other databases as its datastore such as MySQL. As for filestore, PipeCD supports AWS S3 and MINIO as well.

For example, in case of using MySQL as datastore and MINIO as filestore, the Control Plane configuration will be as follows:

apiVersion: "pipecd.dev/v1beta1"
kind: ControlPlane
spec:
  stateKey: {RANDOM_STRING}
  datastore:
    type: MYSQL
    config:
      url: {YOUR_MYSQL_ADDRESS}
      database: {YOUR_DATABASE_NAME}
  filestore:
    type: MINIO
    config:
      endpoint: {YOUR_MINIO_ADDRESS}
      bucket: {YOUR_BUCKET_NAME}
      accessKeyFile: /etc/pipecd-secret/minio-access-key
      secretKeyFile: /etc/pipecd-secret/minio-secret-key
      autoCreateBucket: true

You can find required configurations to use other datastores and filestores from Configuration reference.

Caution: In case of using MySQL as Control Plane’s datastore, please note that the implementation of PipeCD requires some features that are only available in MySQL v8, make sure your MySQL service satisfies the requirement.

3. Accessing the PipeCD web

If your installation includes an ingress, the PipeCD web can be accessed by the ingress’s IP address or domain. Otherwise, private PipeCD web can be accessed by using kubectl port-forward to expose the installed Control Plane on your localhost:

kubectl port-forward svc/pipecd 8080 --namespace={NAMESPACE}

Now go to http://localhost:8080 on your browser, you will see a page to log in to your project.

Up to here, you have an installed PipeCD’s Control Plane. To log in, you need to initialize a new project.

4. Initialize a new project

To create a new project, you need to access the ops pod in your installed PipeCD control plane, using kubectl port-forward command:

kubectl port-forward service/pipecd-ops 9082 --namespace={NAMESPACE}

Then, access http://localhost:9082.

On that page, you will see the list of registered projects and a link to register new projects. Registering a new project requires only a unique ID string and an optional description text.

Once a new project has been registered, a static admin (username, password) will be automatically generated for the project admin, you can use that to log in via the login form in the above section.

For more about adding a new project in detail, please read the following docs.

4’. Upgrade Control Plane version

To upgrade the PipeCD Control Plane, preparations and commands remain as you do when installing PipeCD Control Plane. You only need to change the version flag in command to the specified version you want to upgrade your PipeCD Control Plane to.

helm upgrade -i pipecd oci://ghcr.io/pipe-cd/chart/pipecd --version {NEW_VERSION} --namespace={NAMESPACE} \
  --set-file config.data=path-to-control-plane-configuration-file \
  --set-file secret.encryptionKey.data=path-to-encryption-key-file \
  --set-file secret.firestoreServiceAccount.data=path-to-service-account-file \
  --set-file secret.gcsServiceAccount.data=path-to-service-account-file

Production Hardening

This part provides guidance for a production hardened deployment of the control plane.

  • Publishing the control plane

    You can allow external access to the control plane by enabling the ingress configuration.

  • End-to-End TLS

    After switching to HTTPS, do not forget to set the api.args.secureCookie parameter to be true to disallow using cookies on unsecured HTTP connection.

    Alternatively in the case of GKE Ingress, PipeCD also requires a TLS certificate for internal use. This can be a self-signed one and generated by this command:

    openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN={YOUR_DOMAIN}"
    

    Those key and cert can be configured via secret.internalTLSKey.data and secret.internalTLSCert.data.

    To enable internal TLS connection, please set the gateway.internalTLS.enabled parameter to be true.

    Otherwise, the cloud.google.com/app-protocols annotation should also be configured as the following:

    service:
      port: 443
      annotations:
        cloud.google.com/app-protocols: '{"service":"HTTP2"}'