For the past year, since working on a Kubernetes-based experience for Next 2018, [Kubernetes] and its sidekick [Istio] have been a huge mental block. Docker makes sense, and docker-compose
is intuitive enough for someone like me to make work. But k8s is wrapped in jargon and huge API that makes it daunting, and that's a huge disservice. Kubernetes is a powerful tool for infrastructure automation and scaling, and after the initial legwork can make app dev much easier. No more shitty sysadmin bash scripts to help standup servers.
This is a collection of the process I used to stand up my first real "cluster," and some solid boilerplate yaml that I'll use moving forward. It's still rough, and it'll probably grow over time.
Currently, this only runs on Docker and GCP's GKE.
The gist of it is:
deployments
and services
, and expose a load balancergcloud
.Create cluster:
gcloud beta container clusters create csp-city-test --project=$PROJECT_ID \
--addons=Istio --istio-config=auth=MTLS_STRICT \
--cluster-version=1.11.6-gke.6 \
--machine-type=n1-standard-2 \
--num-nodes=4 \
--zone=us-west1-a
Generate creds:
gcloud container clusters get-credentials csp-city-test --zone=us-west1-a --project=$PROJECT_ID
Check services, get external IP:
kubectl get service -n istio-system
The process is basically the same as git, create a repo here and add it as a remote for any project.
Create repo:
gcloud source repos create REPO_NAME
Commit to the Google Repo:
add .
commit "init"
git push --all google
This step is to automate the build process. We have to tell docker to use Google's Container Registry instead of Docker's, and use this for building images.
gcloud auth configure-docker
gcloud components install docker-credential-gcr
docker-credential-gcr configure-docker
cat creds.json | docker login -u _json_key --password-stdin https://gcr.io
Build Image:
docker tag <repo> gcr.io/<gcp project name>/<repo>
gcloud builds submit "$(pwd)/<dockerfile dir>" --tag=gcr.io/<gcp project name>/<dockerfile dir>
Create some config files to use, two deployments and two services. We'll use an nginx load balancer and a simple node server (the same as here), and expose the nginx container to the web.
Deployment:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.17.0 ()
creationTimestamp: null
labels:
io.kompose.service: server
app: server
name: server
spec:
replicas: 1
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
io.kompose.service: server
app: server # We need this name to link it to nginx
name: server
spec:
containers:
- env:
- name: MESSAGE
value: no. 1
image: <google container registry image> # UPDATE THIS!!!
name: server
resources: {}
tty: true
restartPolicy: Always
status: {}
Service:
apiVersion: v1
kind: Service
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.17.0 ()
creationTimestamp: null
labels:
io.kompose.service: server
name: server
spec:
selector:
app: nginx # The name of the nginx container to link too, in this case "nginx"
ports:
- name: "8000"
port: 8000 # The port the server is listening on
targetPort: 8000
selector:
io.kompose.service: server
status:
loadBalancer: {}
Deployment:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.17.0 ()
creationTimestamp: null
labels:
io.kompose.service: nginx
name: nginx # The name used in the server configs
spec:
replicas: 1
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
io.kompose.service: nginx
spec:
containers:
- image: <google container registry image> # UPDATE THIS!!!
name: nginx
ports:
- containerPort: 8080 # The port nginx is listening on
resources: {}
tty: true
restartPolicy: Always
status: {}
Service:
apiVersion: v1
kind: Service
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.17.0 ()
creationTimestamp: null
labels:
io.kompose.service: nginx
name: nginx # The name used in the server configs
spec:
selector:
app: server # The name of the server
ports:
- name: "8080"
port: 80
targetPort: 8080 # The port nginx is listening on
selector:
io.kompose.service: nginx
type: LoadBalancer
status:
loadBalancer: {}
kubectl create -f <yaml>
for ns in $(kubectl get ns --output=jsonpath={.items[*].metadata.name}); do kubectl delete ns/$ns; done;
kubectl delete deployments --all && kubectl delete services --all
gcloud container clusters delete csp-city-test --zone=us-west1-a