Deploys a Kubernetes cluster and supporting resources
-
Create a GCS bucket for use as a terraform backend.
gsutil mb -l US gs://iskprinter-prod-tf-state
-
Enable versioning on the bucket.
gsutil versioning set on gs://iskprinter-prod-tf-state
-
Install prerequisites, including
minikube
, and start it.brew install minikube brew install --cask docker brew install helm minikube start \ --kubernetes-version=v1.26.1 \ --cpus 4 \ --memory 7951
-
Enable the ingress extension.
minikube addons enable ingress minikube tunnel
-
Set your
/etc/hosts
file as shown below.127.0.0.1 iskprinter-dev.com 127.0.0.1 www.iskprinter-dev.com 127.0.0.1 api.iskprinter-dev.com
- Initialize and deploy the production cluster.
terragrunt apply --terragrunt-working-dir ./config/prod/cluster
- Initialize and deploy the remaining modules, in the following order:
./config/dev/cert-manager
./config/dev/mongodb-operator
- Initialize and deploy the remaining modules, in the following order:
./config/prod/backups
./config/prod/cert-manager-operator
./config/prod/cert-manager-cluster-issuer
./config/prod/container-registries
./config/prod/external-dns
./config/prod/external-secrets-operator
./config/prod/hashicorp-vault
./config/prod/ingress-nginx
./config/prod/mongodb-operator
./config/prod/tekton-pipeline-crds
./config/prod/tekton-dashboard-crds
./config/prod/tekton-triggers-crds
./config/prod/tekton-triggers-interceptors-crds
./config/prod/tekton-pipelines
./config/prod/user-accounts
Annotating this service account will link it to a Google service account with permission to pull images.
- Annotate the Kubernetes service account.
kubectl annotate serviceaccount \ tekton-pipelines-controller \ 'iam.gke.io/gcp-service-account'='tekton-pipelines-controller@cameronhudson8.iam.gserviceaccount.com' \ --context gcp \ -n tekton-pipelines
-
Install the hashicorp vault cli
brew tap hashicorp/tap brew install hashicorp/tap/vault
-
Port-forward the hashicorp vault to your local machine.
kubectl --context gcp -n hashicorp-vault port-forward svc/hashicorp-vault 8200:8200
-
Set the vault address in a shell.
export VAULT_ADDR='http://localhost:8200'
-
Initialize the vault. Save the printed recovery keys initial root token.
vault operator init
-
Set the vault token in your shell.
export VAULT_TOKEN='<initial-root-token>'
-
Create an entity for yourself.
vault write identity/entity name=cameron-hudson
-
Enable the
userpass
login method.vault auth enable userpass
-
Create a user.
vault write auth/userpass/users/cameron-hudson \ password='<password>'
-
Link the user to the entity by adding an entity-alias.
vault write identity/entity-alias name="cameron-hudson" \ canonical_id=$( vault read identity/entity/name/cameron-hudson \ -format=json \ | jq -r '.data.id' ) \ mount_accessor=$( vault auth list \ -format=json \ | jq -r '.["userpass/"].accessor' )
-
Create an
admin
policy.echo ' # Read system health check path "sys/health" { capabilities = ["read", "sudo"] } # Create and manage ACL policies broadly across Vault # List existing policies path "sys/policies/acl" { capabilities = ["list"] } # Create and manage ACL policies path "sys/policies/acl/*" { capabilities = ["create", "read", "update", "delete", "list", "sudo"] } # Enable and manage authentication methods broadly across Vault # Manage auth methods broadly across Vault path "auth/*" { capabilities = ["create", "read", "update", "delete", "list", "sudo"] } # Create, update, and delete auth methods path "sys/auth/*" { capabilities = ["create", "update", "delete", "sudo"] } # List auth methods path "sys/auth" { capabilities = ["read"] } # Enable and manage the key/value secrets engine at `secret/` path # Manage key-value secrets path "secret" { capabilities = ["list"] } path "secret/*" { capabilities = ["create", "read", "update", "delete", "list", "sudo"] } # Manage secrets engines path "sys/mounts/*" { capabilities = ["create", "read", "update", "delete", "list", "sudo"] } # List existing secrets engines. path "sys/mounts" { capabilities = ["read"] } # Manage identities path "identity/*" { capabilities = ["create", "read", "update", "delete", "list", "sudo"] } ' >/tmp/admin-policy.hcl vault policy write admin /tmp/admin-policy.hcl rm /tmp/admin-policy.hcl
-
Create an
admins
group.vault write identity/group name="admins" \ policies=admin \ member_entity_ids=$( vault read identity/entity/name/cameron-hudson \ -format=json \ | jq -r '.data.id' )
-
Sign in with the new user.
unset VAULT_TOKEN vault login -method=userpass username=cameron-hudson
-
Create an entity for external-secrets service.
vault write identity/entity name=external-secrets
-
Enable the
approle
login method.vault auth enable approle
-
Create a
secret-reader
policy.echo ' # Read secrets path "secret/*" { capabilities = ["read"] } ' >/tmp/secret-reader-policy.hcl vault policy write secret-reader /tmp/secret-reader-policy.hcl rm /tmp/secret-reader-policy.hcl
-
Create an approle that belongs to the
secret-readers
group.vault write auth/approle/role/external-secrets \ token_ttl=20m \ token_max_ttl=30m \ policies=secret-reader
-
Create a Secret and ClusterSecretStore resource. (You will have to deindent the following code block if you are viewing this file in a text editor.)
cat <<EOF | kubectl --context gcp apply -f - apiVersion: v1 kind: Secret metadata: namespace: external-secrets-operator name: approle-secret stringData: secretId: $( vault write -f auth/approle/role/external-secrets/secret-id \ -format=json \ | jq -r '.data.secret_id' ) EOF cat <<EOF | kubectl --context gcp apply -f - apiVersion: external-secrets.io/v1beta1 kind: ClusterSecretStore metadata: namespace: external-secrets-operator name: hashicorp-vault-kv spec: provider: vault: server: http://hashicorp-vault-internal.hashicorp-vault.svc.cluster.local:8200 path: secret version: v2 auth: appRole: path: approle roleId: $( vault read auth/approle/role/external-secrets/role-id \ -format=json \ | jq -r '.data.role_id' ) secretRef: namespace: external-secrets-operator name: approle-secret key: secretId EOF
-
Enable the key-value secret store.
vault secrets enable \ -version=2 \ -path=secret \ kv
-
Local Create the
iskprinter
namespace.kubectl --context minikube create namespace iskprinter
-
Create the Eve API credentials. (From https://developers.eveonline.com/applications.)
-
Local (You will have to deindent the following code block if you are viewing this file in a text editor.)
cat <<EOF | kubectl --context minikube apply -f - apiVersion: v1 kind: Secret metadata: namespace: iskprinter name: api-client-credentials stringData: id: <api-client-id> secret: <api-client-secret> EOF
-
Prod
vault kv put secret/api-client-credentials \ id=<client-id> \ secret=<client-secret>
-
-
Create the JWT private and public keys. If you need to create these from scratch, use
openssl
.openssl ecparam \ -name secp521r1 \ -genkey \ -noout \ -out <path-to-private-key> openssl ec \ -in <path-to-private-key> \ -pubout \ -out <path-to-public-key>
-
Local (You will have to deindent the following code block if you are viewing this file in a text editor.)
cat <<EOF | kubectl --context minikube apply -f - apiVersion: v1 kind: Secret metadata: namespace: iskprinter name: iskprinter-jwt-keys stringData: private-key: $(cat <path-to-private-key> | base64) public-key: $(cat <path-to-public-key> | base64) EOF
-
Prod
vault kv put secret/iskprinter-jwt-keys \ public-key=@<path-to-public-key> \ private-key=@<path-to-private-key>
-
-
Prod Add a personal access token so the CICD bot can update the Github build status.
vault kv put secret/cicd-bot-personal-access-token \ username=IskprinterGitBot \ password=<cicd-bot-personal-access-token>
-
Prod Add a Github webhook secret so that the Github status webhook is protected.
vault kv put secret/github-webhook-secret \ secret=<github-webhook-secret>
-
Prod Add an SSH private key and a
known_hosts
file for Github so that the CICD bot can pull code.vault kv put secret/cicd-bot-ssh-key \ ssh-privatekey="$(cat ~/.ssh/IskprinterGitBot.id_rsa)" \ known_hosts="$(ssh-keyscan github.com)"