Export GitHub and Kubernetes Secrets using GitHub Actions CI/CD.
Hello, do you love GitHub Actions so much as we? 👾
I think you want to use Github Secrets to store your environment variables and sync with Kubernetes secrets. All fine when we have the only one production environment.
Add secrets at repository settings
Then easily create a Kubernetes secret contains your picked GitHub Secrets like this:
- uses: Azure/[email protected]
with:
namespace: ${{ env.NAMESPACE }}
secret-type: 'generic'
secret-name: application-secret-name
arguments:
--from-literal=API_SECRET_NAME_ONE=${{ secrets.API_SECRET_NAME_ONE }}
--from-literal=API_SECRET_NAME_TWO=${{ secrets.API_SECRET_NAME_TWO }}
😞 But usually we have multiple environments
And at this moment GitHub does not support environments for Secrets where you can split your keys. For example something like ${{ secrets.production.KEY_NAME }}
.
🤔 Hmm what will be a simple and quick solution without additional coding?
- Right! Use namespace in GitHub Secret names:
${{ secrets.STAGING_KEY_NAME }}
. We can combine shared and namespace secrets between the environment and create Kubernetes secret during the deployment process.
For staging
environment:
- uses: Azure/[email protected]
if: ${{ contains(env.NAMESPACE, 'staging') }}
with:
namespace: staging
secret-type: 'generic'
secret-name: application-secret-name
arguments: |
--from-literal=SOME_KEY=${{ secrets.SOME_KEY }}
--from-literal=SOME_USERNAME=${{ secrets.STAGING_SOME_USERNAME }}
--from-literal=API_KEY_ONE=${{ secrets.STAGING_API_KEY_ONE }}
...
Same code for your production
environment.
It's simple and works flawlessly! But YAML looks big & scary if you have few environments and a lot of secrets for each of them.
Take a look at our dead simple solution!
We know from GitHub Actions docs that secrets has two type of access:
- property dereference syntax
${{ secrets.SOME_ENV }}
- hash-like brackets
${{ secrets['SOME_ENV'] }}
Same time hasformat
function that accepts any number of argument and you can interpolate them as want. Like we needformat('{0}_{1}', 'STAGING', ‘SOME_SECRET')
will return string'STAGING_SOME_SECRET'
. Combine this two knowledges and write a common YAML code that will create secrets for all your environments (in our case staging and production).
Here is:
- uses: Azure/[email protected]
with:
namespace: env.NAMESPACE
secret-type: 'generic'
secret-name: application-secret-name
arguments: |
--from-literal=SHARED_SECRET=${{ secrets.SHARED_SECRET }}
--from-literal=SOME_SECRET_ONE=${{ secrets[format('{0}_{1}', env.NAMESPACE, 'SOME_SECRET_ONE')] }}
--from-literal=SOME_SECRET_TWO=${{ secrets[format('{0}_{1}', env.NAMESPACE, 'SOME_SECRET_TWO')] }}
This create shared secrets for all environments like SHARED_SECRET
and also some specific secrets STAGING_SOME_SECRET_TWO
and PRODUCTION_SOME_SECRET_TWO
as SOME_SECRET_TWO
for related Kubernetes namespaces.
The secret will be created in the cluster context which was set earlier in the workflow by using either azure/aks-set-context
or `azure/k8s-set-context
This Github Secret Azure/k8s-create-secret works with other Kubernetes clusters - only one thing you need to be sure that you're able to run kubectl
command at your cluster. Personally, I test this action on GCP Cluster and Azure Kubernetes Service.
Thanks for reading!