GitOps Deployment Options
July 24, 2023 ยท View on GitHub
Prepare
- Create a Kubernetes cluster with a minimum of 3 nodes and ~8+GB per node (e.g., Standard_DS3_v2). Do not deploy any network policy plugin. Ensure the cluster is reachable by running any kubectl command.
- Fork the repo
- Create a PAT token for the repo (check the repo box as scope)
- Clone the fork to workstation
Note: Start at the root of the directory in the repo
Option 1
Script Install
# PAT token to access Github
export GITHUB_TOKEN="<<PAT TOken>>"
# Github runner
export owner="<<Github user>>"
# FQDN to assign to the Harbor Ingress. eg. {uniquename}.{region}.cloudapp.azure.com if assigning through the Configuration blade of a Azure PublicIP
export registryHost="<<FQDN>>"
# FQDN to assign to the app eg. {uniquename}.{region}.cloudapp.azure.com if assigning through the Configuration blade of a Azure PublicIP
export appHostName="<<FQDN>>"
# Email to use for LetsEncrypt
export cluster_issuer_email="<<EMAIL>>"
# sendGrid API Key for the app to send emails
export sendGridApiKey="<<set the api key>>"
. ./gitops/setup.sh
The cluster components will take around 12 minutes to deploy. You can check the status (all should read True) with the below command
kubectl get Kustomizations -A
Option 2
Alternatively, use the instructions below
Install Flux
curl -s https://fluxcd.io/install.sh | sudo bash
Generate Linkerd v2 certificates
Install Kube-Seal
sudo wget https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.22.0/kubeseal-0.22.0-linux-amd64.tar.gz -O kubeseal.tar.gz
tar -xvzf kubeseal.tar.gz kubeseal && rm kubeseal.tar.gz
sudo install -m 755 kubeseal /usr/local/bin/kubeseal && rm kubeseal
Bootstrap
- Create a PAT token in Github
- Run the bootstrap
# PAT token to access Github
export GITHUB_TOKEN=<PAT TOken>
# Github runner
export owner="<<Github user>>"
flux bootstrap github \
--owner="$owner" \
--repository=cloud-native-app \
--path=gitops/clusters/bootstrap \
--personal
Prepare Repo
wget https://github.com/smallstep/cli/releases/download/v0.23.4/step-cli_0.23.4_amd64.deb
sudo dpkg -i step-cli_0.23.4_amd64.deb
cd gitops/infrastructure/linkerd
step certificate create identity.linkerd.cluster.local ca.crt ca.key \
--profile root-ca --no-password --insecure \
--san identity.linkerd.cluster.local
step certificate create identity.linkerd.cluster.local issuer.crt issuer.key \
--ca ca.crt --ca-key ca.key --profile intermediate-ca --not-after 8760h --no-password --insecure \
--san identity.linkerd.cluster.local
kubectl -n linkerd create secret generic certs \
--from-file=ca.crt --from-file=issuer.crt \
--from-file=issuer.key -oyaml --dry-run=client \
> certs.yaml
kubectl rollout status deployment sealed-secrets-controller -n flux-system
kubeseal --fetch-cert \
--controller-name=sealed-secrets-controller \
--controller-namespace=flux-system \
> ../../../pub-sealed-secrets.pem
kubeseal --format=yaml --cert=../../../pub-sealed-secrets.pem \
< certs.yaml > certs-sealed.yaml
rm certs.yaml ca.crt issuer.crt issuer.key ca.key
cd ../../..
Set the variables required for the deployment
# Email to use for LetsEncrypt
cluster_issuer_email="<<EMAIL>>"
# FQDN to assign to the Harbor Ingress. Eg. {uniquename}.{region}.cloudapp.azure.com if assigning through the Configuration blade of a Azure PublicIP
registryHost="<<FQDN>>"
# sendGrid API Key for the app to send emails
sendGridApiKey="<<set the api key>>"
# FQDN to assign to the app Eg. {uniquename}.{region}.cloudapp.azure.com if assigning through the Configuration blade of a Azure PublicIP
appHostName="<<FQDN>>"
registryUrl=https://$registryHost
appHostDnsLabel=`echo $appHostName | cut -d '.' -f 1`
registryHostDnsLabel=`echo $registryHost | cut -d '.' -f 1`
exp=$(date -d '+8760 hour' +"%Y-%m-%dT%H:%M:%SZ")
kubectl create secret generic gitops-variables --from-literal=registryHost=$registryHost \
--from-literal=registryUrl=$registryUrl \
--from-literal=externalUrl=$registryUrl \
--from-literal=cluster_issuer_email=$cluster_issuer_email \
--from-literal=cicdWebhookHost=$appHostName \
--from-literal=appHostName=$appHostName \
--from-literal=sendGridApiKey=$sendGridApiKey \
--from-literal=registryHostDnsLabel=$registryHostDnsLabel \
--from-literal=appHostDnsLabel=$appHostDnsLabel \
--from-literal=cert_expiry=$exp \
-n flux-system -oyaml --dry-run=client \
> gitops-variables.yaml
kubeseal --format=yaml --cert=pub-sealed-secrets.pem \
< gitops-variables.yaml > gitops-variables-sealed.yaml
rm gitops-variables.yaml
kubectl apply -f gitops-variables-sealed.yaml
rm gitops-variables-sealed.yaml
cd gitops/app/core
kubectl create secret docker-registry regcred \
--docker-server="https://$registryHost" --docker-username=conexp --docker-password=FTA@CNCF0n@zure3 --docker-email=user@mycompany.com -n conexp-mvp -oyaml --dry-run=client \
> regcred-conexp.yaml
kubeseal --format=yaml --cert=../../../pub-sealed-secrets.pem \
< regcred-conexp.yaml > regcred-conexp-sealed.yaml
rm regcred-conexp.yaml
kubectl create secret docker-registry regcred \
--docker-server="https://$registryHost" --docker-username=conexp --docker-password=FTA@CNCF0n@zure3 --docker-email=user@mycompany.com -n conexp-mvp-fn -oyaml --dry-run=client \
> regcred-fn.yaml
kubeseal --format=yaml --cert=../../../pub-sealed-secrets.pem \
< regcred-fn.yaml > regcred-fn-sealed.yaml
rm regcred-fn.yaml
cd ../../..
cd gitops/app/devops
CONFIG="\
{\n
\"auths\": {\n
\"${registryHost}\": {\n
\"username\": \"conexp\",\n
\"password\": \"FTA@CNCF0n@zure3\",\n
\"email\": \"user@mycompany.com\",\n
\"auth\": \"Y29uZXhwOkZUQUBDTkNGMG5AenVyZTM=\"\n
}\n
}\n
}\n"
printf "${CONFIG}" > config.json
kubectl create secret generic regcred --from-file=config.json=config.json -n conexp-mvp-devops -oyaml --dry-run=client > regcred-devops.yaml
rm config.json
kubeseal --format=yaml --cert=../../../pub-sealed-secrets.pem \
< regcred-devops.yaml > regcred-devops-sealed.yaml
rm regcred-devops.yaml
cd ../../..
rm step-cli_0.23.4_amd64.deb pub-sealed-secrets.pem
Commit the Repo
Deploy the app
flux create kustomization cloud-native-app \
--depends-on=flux-system \
--source=flux-system \
--path="gitops/clusters/production" \
--prune=true \
--interval=5m
Reconciliation
Create a webhook for the Github
curl -H "Authorization: token $GITHUB_TOKEN" \
-X POST \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/$owner/cloud-native-app/hooks \
-d "{\"config\":{\"url\":\"https://$appHostName/cd\",\"content_type\":\"json\"}}"
Urls for the components
# Flux UI
kubectl port-forward svc/weave-gitops 9001:9001 -n flux-system
Browse to http://localhost:9001 and use the username/password as admin/flux
# Tekton
kubectl port-forward svc/tekton-dashboard 8080:9097 -n tekton-pipelines
Browse to http://localhost:8080
# Linkerd
kubectl port-forward svc/web 8084:8084 -n linkerd-viz
Browse to http://localhost:8084
#Jaeger
kubectl port-forward svc/jaeger-query 8060:80 -n tracing
Browse to http://localhost:8060
# Grafana
kubectl port-forward deploy/prometheus-grafana 8070:3000 -n monitoring
Browse to http://localhost:8070 and use the username/password as admin/FTA@CNCF0n@zure3
# Prometheus
kubectl port-forward svc/prometheus-kube-prometheus-prometheus 9090:9090 -n monitoring
Browse to http://localhost:9090
# Harbor Url
echo $registryHost
# App Url
echo $appHostName
Invoke the CICD pipeline by making a small edit to the read.me file in Github. Observe the deployment in Tekton Dashboard. The app deployment should take around 5 minutes.
Navigate to the appHost in the browser to test the app.
Test Stub #1