Deploying Argo CD and Sealed Secrets with Helm

Let’s get stuff deployed!

In this tutorial, we will go over the Declarative setup of Argo CD and Sealed Secrets on a Kubernetes cluster.

For deploying Argo CD and Sealed Secrets we will be using Helm Charts. Helm packages all YAML manifests into an organized directory structure and lets you deploy applications with a few CLI commands. When using Helm Charts we can override default parameters in the values.yaml file changing default installation to our needs.

Let’s get started, shall we?

The documentation for Argo CD suggests creating an argocd namespace for deploying Argo CD services and applications. Bitnami Sealed Secrets by default will install the SealedSecret controller into thekube-system namespace. For the purpose of this tutorial let’s create a namespace called shared-services to isolate our services.
Let’s run the following command in the terminal:

Chances are that you found this tutorial because you want to deploy an application from a private repository. In order to do that you need to provide a public and a private key for the target repository. For the purpose of this demo I will omit listing my private key but will provide you with a template that you may use for deploying your app.

Let’s start with Argo CD

The community-maintained Helm chart for Argo CD is available at argo-helm/charts/argo-cd. I recommend using the official documentation as a reference.

Before running helm install we’re going to customize our installation and define the application resources in the values.yaml file.
Here’s what we’re going to do:

  • Set the password for the built-in admin user that has full access to the system. Argo expects the password to be bcrypt hashed. You can create this hash with htpasswd -nbBC 10 “” $password | tr -d ‘:\n’ | sed ‘s/$2y/$2a/'. Change $password to whatever you want.
  • By default, argocd server runs with self-signed TLS enabled. To access Argo UI we need to add -insecure flag in server.extraArgs field.
  • Disable the dex instance that is used for delegating authentication to external identity providers.

Let’s grab the public key of the connected git repository (check your ~/.ssh/known_hosts file).

Applications in Argo CD are defined by two key blocks of information:

  • source sets the URL for the source repository and Git path for the manifests with the desired state. You can add the target revision field to explicitly specify the branch. Argo CD will monitor for any changes and will apply them automatically.
  • destination defines the target cluster and namespace. By default, it will deploy to the context currently selected in the kubeconfig.

It has been established as the best practice to have separate repositories for application source code and application configuration code (Kubernetes manifest files).

A deployed application will have OutOfSync status if its actual state in the cluster is different from the manifest file in the repository that serves as the source of truth.

Here’s a customized values file for Argo CD

To spin up an instance of Argo CD add the chart repo and run helm install with the modified values.yaml file. Use the --atomic flag to delete created resources if some of the components fail during installation.

There’s one more thing we need to do. Without providing a private ssh key for a git repository, Argo CD won’t be able to retrieve deployment manifests for your application. Repository details are stored in secrets. To avoid security risks we will use the Sealed Secrets tool to safely store the ssh key in the version control.

Secret

A Secret is a Kubernetes object that contains sensitive information such as access tokens, basic-auth credentials, TLS certificates, and so on. Just like ConfigMaps they contain key-value pairs and are used to manage the application deployment.

Here’s an example of the secret with repository credentials (ssh key is omitted):

Make sure to tab 4 spaces when copying your key. You can also add it in one line by encoding your key in Base64. It would look like this: sshPrivateKey: c3NoUHgm9F4pO5KHk2gJpdmF0ZUtleQo=

Let’s see how we can seal the secret.

Sealed Secrets

Sealed Secrets installation is comprised of two parts:
- A controller that runs in-cluster
- A kubeseal CLI

When you deploy the Sealed Secret Controller in a cluster it generates a public and a private key. The public key is used by kubeseal CLI for encryption and the private key is used for decrypting the SealedSecrets CRDs into Kubernetes Secrets.

Sealed-secret certificates are automatically renewed every 30 days and you should always rotate your secrets.

Let’s install the Sealed Secrets controller first. For the installation, we will change the target namespace to “shared-services”. Our values.yaml file will have only one line with the target namespace:

Add the repository and run helm install

Let’s check the status of the installation by running helm list -A which lists all installations across all namespaces. We can see that both Argo CD and Sealed-Secrets releases are installed in the “shared-services” namespace.

To install kubeseal CLI you can use Homebrew for macOS, or install the binary from the GitHub page for Linux:

Now use kubeseal to retrieve the certificate from the controller. Because we installed the controller to a different namespace than the default kube-system, we need to provide this namespace to the kubeseal CLI:

The public key can be safely stored in version control and can be used to encrypt secrets without direct access to the Kubernetes cluster.

kubeseal will use the fetched certificate to encrypt Kubernetes secrets. That’s how you’d encrypt a secret with kubeseal utility:

The command above creates a SealedSecret CRD that looks like this:

It’s important to be aware that the SealedSecret and Kubernetes Secret must share the same namespace, otherwise the controller won’t decrypt the SealedSecret.

Now apply the Sealed Secret to the cluster:

Once a SealedSecret CRD is deployed to the cluster, the controller will pick it up, decrypt it using the private key, and deploy a normal Kubernetes Secret into the same namespace. After this action, the YAML file with the unsealed secret may be deleted as we no longer need it.

Let’s check if our secret was successfully decrypted and deployed by the controller.

Now let’s check if Argo CD was able to successfully connect to the private repository and deploy our application. By default, the Argo CD API server is not exposed to an external IP. To access the API server, we will expose the Argo CD to localhost:8080 (I’m using k9s but you can do it with kubectl by runningkubectl port-forward svc/argocd-server -n shared-services 8080:443)

To log in we can use admin user and the password “argo-demo” (as we defined it in the values.yaml file).

When we navigate to connected repositories we can see that the specified repository has successful connection status. It means that the Sealed Secret controller successfully decrypted and deployed the Secret with the repository information.

ArgoCD is deployed and syncing the application in a cluster.

All resources and actions described above are available at https://github.com/roman-hds/argo-demo

Join FAUN: Website 💻|Podcast 🎙️|Twitter 🐦|Facebook 👥|Instagram 📷|Facebook Group 🗣️|Linkedin Group 💬| Slack 📱|Cloud Native News 📰|More.

If this post was helpful, please click the clap 👏 button below a few times to show your support for the author 👇

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

No responses yet

What are your thoughts?