<< Previous section: Common setup
| Next section: GKE advanced setup in Production >>
- [PE-GCP] Create the GKE cluster
- [PE-GCP] Deploy the Nginx Ingress controller
- [PE-GCP] Create the Google Service Account to access the GKE cluster
- [PE-HUM] Create the GKE access resource definition
- [PE-HUM] Create the Staging Environment
- [PE-GCP] Create a Memorystore (Redis) database
- [PE-HUM] Create the Memorystore (Redis) access resource definition
- [PE-HUM] Deploy the Staging Environment
- Test the Online Boutique website
flowchart LR
subgraph Humanitec
direction LR
subgraph onlineboutique-app [Online Boutique App]
subgraph Staging
direction LR
cartservice-workload([cartservice])
frontend-workload([frontend])
end
end
subgraph Resources
gke-basic-connection>gke-basic-connection]
redis-cart-connection>redis-cart-connection]
end
end
subgraph Google Cloud
direction TB
subgraph gke-basic
subgraph ingress-controller
nginx{{nginx}}
end
subgraph onlineboutique
frontend-->cartservice
end
nginx-->frontend
end
gke-admin-gsa[\gke-admin-gsa/]
gke-basic-connection-.->gke-admin-gsa
gke-admin-gsa-->gke-basic
redis-cart-connection-.->memorystore[(memorystore)]
onlineboutique-app-->onlineboutique
cartservice-->memorystore
end
enduser((End user))-->nginx
PROJECT_ID=FIXME
gcloud config set project ${PROJECT_ID}
CLUSTER_NAME=gke-basic
REGION=northamerica-northeast1
ZONE=${REGION}-a
NETWORK=default
HUMANITEC_IP_ADDRESSES="34.159.97.57/32,35.198.74.96/32,34.141.77.162/32,34.89.188.214/32,34.159.140.35/32,34.89.165.141/32"
LOCAL_IP_ADRESS=$(curl -s ifconfig.co)
HUMANITEC_ORG=FIXME
export HUMANITEC_CONTEXT=/orgs/${HUMANITEC_ORG}
export HUMANITEC_TOKEN=FIXME
ENVIRONMENT=${STAGING_ENV}
As Platform Engineer, in Google Cloud.
gcloud services enable container.googleapis.com
gcloud container clusters create ${CLUSTER_NAME} \
--zone ${ZONE} \
--network ${NETWORK} \
--workload-pool=${PROJECT_ID}.svc.id.goog \
--scopes cloud-platform \
--enable-master-authorized-networks \
--master-authorized-networks ${HUMANITEC_IP_ADDRESSES},${LOCAL_IP_ADRESS}/32 \
--no-enable-google-cloud-access \
--machine-type n2d-standard-4
gcloud container clusters get-credentials ${CLUSTER_NAME} \
--zone ${ZONE}
As Platform Engineer, in Google Cloud.
Deploy the Nginx Ingress Controller:
helm upgrade \
--install ingress-nginx ingress-nginx \
--repo https://kubernetes.github.io/ingress-nginx \
--namespace ingress-nginx \
--create-namespace
Grab the Public IP address of that Ingress Controller:
INGRESS_IP=$(kubectl get svc ingress-nginx-controller \
-n ingress-nginx \
-o jsonpath="{.status.loadBalancer.ingress[*].ip}")
echo ${INGRESS_IP}
Note: re-run the above command until you get a value.
As Platform Engineer, in Google Cloud.
Create the Google Service Account (GSA) with the appropriate role:
GKE_ADMIN_SA_NAME=humanitec-to-${CLUSTER_NAME}
GKE_ADMIN_SA_ID=${GKE_ADMIN_SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com
gcloud iam service-accounts create ${GKE_ADMIN_SA_NAME} \
--display-name=${GKE_ADMIN_SA_NAME}
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member "serviceAccount:${GKE_ADMIN_SA_ID}" \
--role "roles/container.admin"
Download locally the GSA key:
gcloud iam service-accounts keys create ${GKE_ADMIN_SA_NAME}.json \
--iam-account ${GKE_ADMIN_SA_ID}
As Platform Engineer, in Humanitec.
Create the GKE access resource definition:
cat <<EOF > ${CLUSTER_NAME}.yaml
apiVersion: core.api.humanitec.io/v1
kind: Definition
metadata:
id: ${CLUSTER_NAME}
object:
name: ${CLUSTER_NAME}
type: k8s-cluster
driver_type: humanitec/k8s-cluster-gke
driver_inputs:
values:
loadbalancer: ${INGRESS_IP}
name: ${CLUSTER_NAME}
project_id: ${PROJECT_ID}
zone: ${ZONE}
secrets:
credentials: $(cat ${GKE_ADMIN_SA_NAME}.json)
criteria:
- env_id: ${ENVIRONMENT}
EOF
humctl create \
-f ${CLUSTER_NAME}.yaml
With curl.
cat <<EOF > ${CLUSTER_NAME}.yaml
id: ${CLUSTER_NAME}
name: ${CLUSTER_NAME}
type: k8s-cluster
driver_type: humanitec/k8s-cluster-gke
driver_inputs:
values:
loadbalancer: ${INGRESS_IP}
name: ${CLUSTER_NAME}
project_id: ${PROJECT_ID}
zone: ${ZONE}
secrets:
credentials: $(cat ${GKE_ADMIN_SA_NAME}.json)
criteria:
- env_id: ${ENVIRONMENT}
EOF
yq -o json ${CLUSTER_NAME}.yaml > ${CLUSTER_NAME}.json
curl "https://api.humanitec.io/orgs/${HUMANITEC_ORG}/resources/defs" \
-X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${HUMANITEC_TOKEN}" \
-d @${CLUSTER_NAME}.json
Clean sensitive information locally:
rm ${GKE_ADMIN_SA_NAME}.json
rm ${CLUSTER_NAME}.yaml
rm ${CLUSTER_NAME}.json
As Platform Engineer, in Humanitec.
Create the new Environment by cloning the existing Environment from its latest Deployment:
CLONED_ENVIRONMENT=development
humctl create environment ${ENVIRONMENT} \
--name Staging \
-t ${ENVIRONMENT} \
--context /orgs/${HUMANITEC_ORG}/apps/${ONLINEBOUTIQUE_APP} \
--from ${CLONED_ENVIRONMENT}
With curl.
Get the latest Deployment's id of the existing Environment:
CLONED_ENVIRONMENT=development
LAST_DEPLOYMENT_IN_CLONED_ENVIRONMENT=$(curl "https://api.humanitec.io/orgs/${HUMANITEC_ORG}/apps/${ONLINEBOUTIQUE_APP}/envs/${CLONED_ENVIRONMENT}/deploys" \
-s \
-H "Authorization: Bearer ${HUMANITEC_TOKEN}" \
-H "Content-Type: application/json" \
| jq -r .[0].id)
Create the new Environment by cloning the existing Environment from its latest Deployment:
cat <<EOF > ${ONLINEBOUTIQUE_APP}-${ENVIRONMENT}-env.yaml
from_deploy_id: ${LAST_DEPLOYMENT_IN_CLONED_ENVIRONMENT}
id: ${ENVIRONMENT}
name: Staging
type: ${STAGING_ENV}
EOF
yq -o json ${ONLINEBOUTIQUE_APP}-${ENVIRONMENT}-env.yaml > ${ONLINEBOUTIQUE_APP}-${ENVIRONMENT}-env.json
curl "https://api.humanitec.io/orgs/${HUMANITEC_ORG}/apps/${ONLINEBOUTIQUE_APP}/envs" \
-X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${HUMANITEC_TOKEN}" \
-d @${ONLINEBOUTIQUE_APP}-${ENVIRONMENT}-env.json
Deploy the new Environment:
humctl deploy env ${CLONED_ENVIRONMENT} ${ENVIRONMENT} \
--context /orgs/${HUMANITEC_ORG}/apps/${ONLINEBOUTIQUE_APP}
At this stage, you can already test the Online Boutique website in its existing state.
As Platform Engineer, in Google Cloud.
Create the Memorystore (Redis) database with a password in same region and network as the GKE cluster:
gcloud services enable redis.googleapis.com
REDIS_NAME=redis-cart-${ENVIRONMENT}
gcloud redis instances create ${REDIS_NAME} \
--size 1 \
--region ${REGION} \
--zone ${ZONE} \
--network ${NETWORK} \
--redis-version redis_6_x \
--enable-auth
REDIS_HOST=$(gcloud redis instances describe ${REDIS_NAME} \
--region ${REGION} \
--format 'get(host)')
echo ${REDIS_HOST}
REDIS_PORT=$(gcloud redis instances describe ${REDIS_NAME} \
--region ${REGION} \
--format 'get(port)')
echo ${REDIS_PORT}
REDIS_AUTH=$(gcloud redis instances get-auth-string ${REDIS_NAME} \
--region ${REGION} \
--format 'get(authString)')
echo ${REDIS_AUTH}
Note: re-run the above commands until you get the 3 values.
As Platform Engineer, in Humanitec.
cat <<EOF > ${REDIS_NAME}.yaml
apiVersion: core.api.humanitec.io/v1
kind: Definition
metadata:
id: ${REDIS_NAME}
object:
name: ${REDIS_NAME}
type: redis
driver_type: humanitec/static
driver_inputs:
values:
host: ${REDIS_HOST}
port: ${REDIS_PORT}
secrets:
username: ""
password: ${REDIS_AUTH}
criteria:
- env_id: ${ENVIRONMENT}
EOF
humctl create \
-f ${REDIS_NAME}.yaml
With curl.
cat <<EOF > ${REDIS_NAME}.yaml
id: ${REDIS_NAME}
name: ${REDIS_NAME}
type: redis
driver_type: humanitec/static
driver_inputs:
values:
host: ${REDIS_HOST}
port: ${REDIS_PORT}
secrets:
username: ""
password: ${REDIS_AUTH}
criteria:
- env_id: ${ENVIRONMENT}
EOF
yq -o json ${REDIS_NAME}.yaml > ${REDIS_NAME}.json
curl "https://api.humanitec.io/orgs/${HUMANITEC_ORG}/resources/defs" \
-X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${HUMANITEC_TOKEN}" \
-d @${REDIS_NAME}.json
Clean sensitive information locally:
rm ${REDIS_NAME}.yaml
As Platform Engineer, in Humanitec.
Deploy the new Environment to take into account all the new resource definitions:
humctl deploy env ${ENVIRONMENT} ${ENVIRONMENT} \
--context /orgs/${HUMANITEC_ORG}/apps/${ONLINEBOUTIQUE_APP}
Get the public DNS exposing the frontend
Workload:
echo -e "https://$(humctl get active-resources \
--context /orgs/${HUMANITEC_ORG}/apps/${ONLINEBOUTIQUE_APP}/envs/${ENVIRONMENT} \
-o json \
| jq -c '.[] | select(.object.type | contains("dns"))' \
| jq -r .object.resource.host)"
With curl.
echo -e "https://$(curl "https://api.humanitec.io/orgs/${HUMANITEC_ORG}/apps/${ONLINEBOUTIQUE_APP}/envs/${ENVIRONMENT}/resources" \
-s \
-H "Authorization: Bearer ${HUMANITEC_TOKEN}" \
-H "Content-Type: application/json" \
| jq -c '.[] | select(.type | contains("dns"))' \
| jq -r .resource.host)"
Note: re-run the above command until you get a value.