├── .gitignore ├── README.md ├── rbac ├── rolebinding.yml ├── README.md ├── role.yml └── init.sh ├── persistent-volume ├── minikube │ ├── pv-claim.yaml │ ├── pv.yaml │ ├── statefulset-restore.yaml │ ├── statefulset.yaml │ └── demo.sh ├── aws │ ├── pv-claim.yaml │ ├── pv.yaml │ ├── statefulset-restore.yaml │ ├── statefulset.yaml │ └── demo.sh └── util.sh ├── apps ├── busybox.yml ├── nginx.yaml └── joatmon08-hello.yaml ├── LICENSE.md └── logging └── fluentd_daemonset.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | *.crt 2 | *.csr 3 | *.key 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kubernetes-reference 2 | References outlining some key Kubernetes deployments/constructs. 3 | -------------------------------------------------------------------------------- /rbac/rolebinding.yml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: RoleBinding 3 | apiVersion: rbac.authorization.k8s.io/v1beta1 4 | metadata: 5 | name: deployment-manager-binding 6 | namespace: test 7 | subjects: 8 | - kind: User 9 | name: joatmon08 10 | apiGroup: "" 11 | roleRef: 12 | kind: Role 13 | name: deployment-manager 14 | apiGroup: "" 15 | -------------------------------------------------------------------------------- /persistent-volume/minikube/pv-claim.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: PersistentVolumeClaim 3 | apiVersion: v1 4 | metadata: 5 | name: www-claim 6 | spec: 7 | storageClassName: standard 8 | accessModes: 9 | - ReadWriteOnce 10 | resources: 11 | requests: 12 | storage: 1Gi 13 | volumeName: pvc-f2617ebf-3e0b-11e8-b2b3-080027732cee -------------------------------------------------------------------------------- /persistent-volume/aws/pv-claim.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: PersistentVolumeClaim 4 | metadata: 5 | labels: 6 | app: hello-stateful 7 | name: joatmon08-pvc 8 | spec: 9 | accessModes: 10 | - ReadWriteOnce 11 | resources: 12 | requests: 13 | storage: 1Gi 14 | storageClassName: gp2 15 | volumeName: joatmon08-pv 16 | -------------------------------------------------------------------------------- /persistent-volume/aws/pv.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: PersistentVolume 4 | metadata: 5 | name: joatmon08-pv 6 | spec: 7 | storageClassName: gp2 8 | accessModes: 9 | - ReadWriteOnce 10 | capacity: 11 | storage: 1Gi 12 | persistentVolumeReclaimPolicy: Delete 13 | awsElasticBlockStore: 14 | fsType: ext4 15 | volumeID: aws://{{ AWS region }}/{{ volume ID }} 16 | -------------------------------------------------------------------------------- /persistent-volume/minikube/pv.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: PersistentVolume 3 | apiVersion: v1 4 | metadata: 5 | name: pvc-f2617ebf-3e0b-11e8-b2b3-080027732cee 6 | spec: 7 | storageClassName: standard 8 | accessModes: 9 | - ReadWriteOnce 10 | capacity: 11 | storage: 1Gi 12 | persistentVolumeReclaimPolicy: Delete 13 | hostPath: 14 | path: "/tmp/hostpath-provisioner/pvc-f2617ebf-3e0b-11e8-b2b3-080027732cee" -------------------------------------------------------------------------------- /apps/busybox.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: busybox 6 | labels: 7 | app: busybox 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: busybox 13 | template: 14 | metadata: 15 | labels: 16 | app: busybox 17 | spec: 18 | containers: 19 | - name: busybox 20 | image: busybox 21 | command: 22 | - "sleep" 23 | - "3600" 24 | -------------------------------------------------------------------------------- /rbac/README.md: -------------------------------------------------------------------------------- 1 | # k8s-rbac 2 | This is a reference for implementing RBAC for a user, limited to a 3 | specific namespace. 4 | 5 | ## Usage 6 | * Run `./init.sh $CERT_PATH $CLUSTER $NAMESPACE $USERNAME` 7 | * Update role.yml and rolebinding.yml with the correct namespace 8 | and users. 9 | * Apply to the cluster. 10 | ``` 11 | kubectl apply -f role.yml 12 | kubectl delete -f rolebinding.yml 13 | ``` 14 | * To use the context, add the `--context` option. 15 | ``` 16 | kubectl --context=$USERNAME-context get pods 17 | ``` 18 | -------------------------------------------------------------------------------- /rbac/role.yml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: Role 3 | apiVersion: rbac.authorization.k8s.io/v1beta1 4 | metadata: 5 | namespace: test 6 | name: deployment-manager 7 | rules: 8 | - apiGroups: ["", "extensions", "apps"] 9 | resources: ["deployments", "replicasets"] 10 | verbs: ["get", "list", "create", "delete", "update"] 11 | - apiGroups: [""] 12 | resources: ["services", "secrets", "configmaps"] 13 | verbs: ["get", "list", "create", "delete"] 14 | - apiGroups: [""] 15 | resources: ["pods"] 16 | verbs: ["get", "list"] 17 | -------------------------------------------------------------------------------- /apps/nginx.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1beta2 3 | kind: Deployment 4 | metadata: 5 | name: nginx 6 | spec: 7 | selector: 8 | matchLabels: 9 | run: nginx 10 | replicas: 1 11 | template: 12 | metadata: 13 | labels: 14 | run: nginx 15 | spec: 16 | containers: 17 | - name: nginx 18 | image: nginx 19 | ports: 20 | - containerPort: 80 21 | --- 22 | apiVersion: v1 23 | kind: Service 24 | metadata: 25 | name: nginx 26 | labels: 27 | run: nginx 28 | spec: 29 | ports: 30 | - port: 80 31 | selector: 32 | run: nginx -------------------------------------------------------------------------------- /rbac/init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $# -ne 4 ]; then 4 | echo "Got ${#} arguments" 5 | exit 1 6 | fi 7 | 8 | CERT_PATH=$1 9 | CLUSTER=$2 10 | NAMESPACE=$3 11 | USERNAME=$4 12 | 13 | client_cert=$1/$2/ca.crt 14 | client_key=$1/$2/ca.key 15 | 16 | kubectl create namespace $NAMESPACE 17 | openssl genrsa -out user.key 4096 18 | openssl req -new -key user.key -out user.csr -subj "/CN=$USERNAME/O=developer" 19 | openssl x509 -req -in user.csr -CA $client_cert -CAkey $client_key -CAcreateserial -out user.crt -days 10 20 | kubectl config set-credentials $USERNAME --client-certificate=user.crt --client-key=user.key 21 | kubectl config set-context $USERNAME-context --cluster=$CLUSTER --namespace=$NAMESPACE --user=$USERNAME 22 | -------------------------------------------------------------------------------- /apps/joatmon08-hello.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1beta2 2 | kind: Deployment 3 | metadata: 4 | name: joatmon08-hello 5 | spec: 6 | selector: 7 | matchLabels: 8 | run: joatmon08-hello 9 | replicas: 1 10 | template: 11 | metadata: 12 | labels: 13 | run: joatmon08-hello 14 | spec: 15 | containers: 16 | - name: joatmon08-hello 17 | image: joatmon08/hello 18 | ports: 19 | - containerPort: 8001 20 | protocol: TCP 21 | name: http 22 | - containerPort: 8002 23 | protocol: TCP 24 | name: metric 25 | --- 26 | apiVersion: v1 27 | kind: Service 28 | metadata: 29 | name: joatmon08-hello 30 | labels: 31 | run: joatmon08-hello 32 | spec: 33 | ports: 34 | - port: 8001 35 | protocol: TCP 36 | name: http 37 | - port: 8002 38 | protocol: TCP 39 | name: metric 40 | selector: 41 | run: joatmon08-hello -------------------------------------------------------------------------------- /persistent-volume/aws/statefulset-restore.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: hello-stateful 6 | labels: 7 | app: hello-stateful 8 | spec: 9 | clusterIP: None 10 | selector: 11 | app: hello-stateful 12 | --- 13 | apiVersion: apps/v1 14 | kind: StatefulSet 15 | metadata: 16 | name: hello-stateful 17 | spec: 18 | selector: 19 | matchLabels: 20 | app: hello-stateful 21 | serviceName: hello-stateful 22 | replicas: 1 23 | template: 24 | metadata: 25 | labels: 26 | app: hello-stateful 27 | spec: 28 | terminationGracePeriodSeconds: 10 29 | containers: 30 | - name: hello-stateful 31 | image: joatmon08/hello-stateful:1.0 32 | volumeMounts: 33 | - name: log 34 | mountPath: /usr/share/hello 35 | volumes: 36 | - name: log 37 | persistentVolumeClaim: 38 | claimName: joatmon08-pvc -------------------------------------------------------------------------------- /persistent-volume/minikube/statefulset-restore.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: nginx 6 | labels: 7 | app: nginx 8 | spec: 9 | ports: 10 | - port: 80 11 | name: web 12 | clusterIP: None 13 | selector: 14 | app: nginx 15 | --- 16 | apiVersion: apps/v1 17 | kind: StatefulSet 18 | metadata: 19 | name: web 20 | spec: 21 | selector: 22 | matchLabels: 23 | app: nginx 24 | serviceName: "nginx" 25 | replicas: 1 26 | template: 27 | metadata: 28 | labels: 29 | app: nginx 30 | spec: 31 | terminationGracePeriodSeconds: 10 32 | containers: 33 | - name: nginx 34 | image: k8s.gcr.io/nginx-slim:0.8 35 | ports: 36 | - containerPort: 80 37 | name: web 38 | volumeMounts: 39 | - name: www 40 | mountPath: /usr/share/nginx/html 41 | volumes: 42 | - name: www 43 | persistentVolumeClaim: 44 | claimName: www-claim -------------------------------------------------------------------------------- /persistent-volume/aws/statefulset.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: hello-stateful 6 | labels: 7 | app: hello-stateful 8 | spec: 9 | clusterIP: None 10 | selector: 11 | app: hello-stateful 12 | --- 13 | apiVersion: apps/v1 14 | kind: StatefulSet 15 | metadata: 16 | name: hello-stateful 17 | spec: 18 | selector: 19 | matchLabels: 20 | app: hello-stateful 21 | serviceName: hello-stateful 22 | replicas: 1 23 | template: 24 | metadata: 25 | labels: 26 | app: hello-stateful 27 | spec: 28 | terminationGracePeriodSeconds: 10 29 | containers: 30 | - name: hello-stateful 31 | image: joatmon08/hello-stateful:1.0 32 | volumeMounts: 33 | - name: log 34 | mountPath: /usr/share/hello 35 | volumeClaimTemplates: 36 | - metadata: 37 | name: log 38 | spec: 39 | accessModes: [ "ReadWriteOnce" ] 40 | storageClassName: gp2 41 | resources: 42 | requests: 43 | storage: 1Gi -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2018 Rosemary Wang 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /persistent-volume/minikube/statefulset.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: nginx 6 | labels: 7 | app: nginx 8 | spec: 9 | ports: 10 | - port: 80 11 | name: web 12 | clusterIP: None 13 | selector: 14 | app: nginx 15 | --- 16 | apiVersion: apps/v1 17 | kind: StatefulSet 18 | metadata: 19 | name: web 20 | spec: 21 | selector: 22 | matchLabels: 23 | app: nginx 24 | serviceName: "nginx" 25 | replicas: 1 26 | template: 27 | metadata: 28 | labels: 29 | app: nginx 30 | spec: 31 | terminationGracePeriodSeconds: 10 32 | containers: 33 | - name: nginx 34 | image: k8s.gcr.io/nginx-slim:0.8 35 | ports: 36 | - containerPort: 80 37 | name: web 38 | volumeMounts: 39 | - name: www 40 | mountPath: /usr/share/nginx/html 41 | volumeClaimTemplates: 42 | - metadata: 43 | name: www 44 | spec: 45 | accessModes: [ "ReadWriteOnce" ] 46 | storageClassName: standard 47 | resources: 48 | requests: 49 | storage: 1Gi -------------------------------------------------------------------------------- /logging/fluentd_daemonset.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: fluentdconf 6 | namespace: kube-system 7 | data: 8 | fluent.conf: | 9 | 10 | @type null 11 | 12 | 13 | 14 | @type tail 15 | path /var/log/containers/*.log 16 | pos_file /var/log/fluentd-containers.log.pos 17 | time_format %Y-%m-%dT%H:%M:%S.%NZ 18 | tag kubernetes.* 19 | format json 20 | read_from_head true 21 | 22 | 23 | 24 | @type kubernetes_metadata 25 | 26 | 27 | 28 | @type null 29 | 30 | 31 | 32 | @type null 33 | 34 | 35 | 36 | @type stdout 37 | 38 | --- 39 | apiVersion: extensions/v1beta1 40 | kind: DaemonSet 41 | metadata: 42 | name: fluentd 43 | namespace: kube-system 44 | labels: 45 | k8s-app: fluentd-logging 46 | version: v1 47 | kubernetes.io/cluster-service: "true" 48 | spec: 49 | template: 50 | metadata: 51 | labels: 52 | k8s-app: fluentd-logging 53 | version: v1 54 | kubernetes.io/cluster-service: "true" 55 | spec: 56 | tolerations: 57 | - key: node-role.kubernetes.io/master 58 | effect: NoSchedule 59 | containers: 60 | - name: fluentd 61 | image: fluent/fluentd-kubernetes-daemonset:v0.12-alpine-elasticsearch 62 | resources: 63 | limits: 64 | memory: 200Mi 65 | requests: 66 | cpu: 100m 67 | memory: 200Mi 68 | volumeMounts: 69 | - name: fluentconfig 70 | mountPath: /fluentd/etc/ 71 | - name: varlog 72 | mountPath: /var/log 73 | - name: varlibdockercontainers 74 | mountPath: /var/lib/docker/containers 75 | readOnly: true 76 | terminationGracePeriodSeconds: 30 77 | volumes: 78 | - name: fluentconfig 79 | configMap: 80 | name: fluentdconf 81 | - name: varlog 82 | hostPath: 83 | path: /var/log 84 | - name: varlibdockercontainers 85 | hostPath: 86 | path: /var/lib/docker/containers 87 | -------------------------------------------------------------------------------- /persistent-volume/util.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2016 The Kubernetes Authors All rights reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | readonly reset=$(tput sgr0) 17 | readonly green=$(tput bold; tput setaf 2) 18 | readonly yellow=$(tput bold; tput setaf 3) 19 | readonly blue=$(tput bold; tput setaf 6) 20 | readonly timeout=$(if [ "$(uname)" == "Darwin" ]; then echo "1"; else echo "0.1"; fi) 21 | readonly ipv6regex='(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))' 22 | 23 | function desc() { 24 | maybe_first_prompt 25 | echo "$blue# $@$reset" 26 | prompt 27 | } 28 | 29 | function desc_rate() { 30 | maybe_first_prompt 31 | rate=30 32 | if [ -n "$DEMO_RUN_FAST" ]; then 33 | rate=1000 34 | fi 35 | echo "$blue# $@$reset" | pv -qL $rate 36 | prompt 37 | } 38 | 39 | function prompt() { 40 | echo -n "$yellow\$ $reset" 41 | } 42 | 43 | started="" 44 | function maybe_first_prompt() { 45 | if [ -z "$started" ]; then 46 | prompt 47 | started=true 48 | fi 49 | } 50 | 51 | # After a `run` this variable will hold the stdout of the command that was run. 52 | # If the command was interactive, this will likely be garbage. 53 | DEMO_RUN_STDOUT="" 54 | 55 | function run() { 56 | maybe_first_prompt 57 | rate=50 58 | if [ -n "$DEMO_RUN_FAST" ]; then 59 | rate=1000 60 | fi 61 | echo "$green$1$reset" | pv -qL $rate 62 | if [ -n "$DEMO_RUN_FAST" ]; then 63 | sleep 0.5 64 | fi 65 | OFILE="$(mktemp -t $(basename $0).XXXXXX)" 66 | script -q "$OFILE" /bin/bash -c "$1" 67 | r=$? 68 | read -d '' -t "${timeout}" -n 10000 # clear stdin 69 | prompt 70 | if [ -z "$DEMO_AUTO_RUN" ]; then 71 | read -s 72 | fi 73 | DEMO_RUN_STDOUT="$(tail -n +2 $OFILE | sed 's/\r//g')" 74 | return $r 75 | } 76 | 77 | function relative() { 78 | for arg; do 79 | echo "$(realpath $(dirname $(which $0)))/$arg" | sed "s|$(realpath $(pwd))|.|" 80 | done 81 | } 82 | 83 | trap "echo" EXIT 84 | -------------------------------------------------------------------------------- /persistent-volume/aws/demo.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | . ../util.sh 3 | 4 | desc "Create the StatefulSet." 5 | run "kubectl apply -f statefulset.yaml" 6 | 7 | volume=$(kubectl get pvc | grep hello | tail -n 1 | cut -d' ' -f9) 8 | pvc=$(kubectl get pvc | grep hello | tail -n 1 | cut -d' ' -f1) 9 | pod=$(kubectl get pods | grep hello | cut -d' ' -f1) 10 | 11 | desc "Get the output of the stateful.log file." 12 | run "kubectl exec ${pod} -- cat /usr/share/hello/stateful.log" 13 | 14 | desc "Delete the StatefulSet." 15 | run "kubectl delete -f statefulset.yaml --ignore-not-found" 16 | 17 | desc "Does the volume and claim still exist?" 18 | run "kubectl get pv" 19 | run "kubectl get pvc" 20 | run "kubectl get statefulsets" 21 | desc "Yes, the volume and claim still exist!" 22 | 23 | desc "Let's bring the StatefulSet back up." 24 | run "kubectl apply -f statefulset.yaml" 25 | 26 | desc "Does the volume get reattached?" 27 | desc "Let's check the statefulset.log for previous log messages." 28 | run "kubectl exec ${pod} -- cat /usr/share/hello/stateful.log" 29 | desc "Yes, the volume is reattached." 30 | 31 | desc "We'll back up the volume with an AWS snapshot." 32 | volumeID=$(kubectl get pv ${volume} -o jsonpath='{.spec.awsElasticBlockStore.volumeID}' | cut -d'/' -f4) 33 | run "aws ec2 create-snapshot --volume-id ${volumeID} --region=${REGION}" 34 | 35 | desc "Let's capture the last known written log file line." 36 | lastline=$(kubectl exec ${pod} -- cat /usr/share/hello/stateful.log | tail -n 1) 37 | 38 | desc "Let's delete the statefulset, but keep the pvc & pv." 39 | run "kubectl delete -f statefulset.yaml" 40 | desc "And let's delete the backend volume, as if something went wrong." 41 | run "aws ec2 delete-volume --volume-id ${volumeID} --region=${REGION}" 42 | 43 | desc "What happens when I access my stateful logs?" 44 | run "kubectl exec ${pod} -- cat /usr/share/hello/stateful.log" 45 | 46 | desc "Oh no!" 47 | run "kubectl get pvc" 48 | run "kubectl get pv" 49 | 50 | desc "But yet the pvc and pv are still there..." 51 | 52 | desc "There's a possibility that we can create a new statefulset and reattach the volume." 53 | desc "Let's restore the volume with our snapshot." 54 | run "aws ec2 create-volume --availability-zone=${REGION}a --snapshot-id ${snapshotID} --region=${REGION} --volume-type gp2 --tag-specifications 'ResourceType=volume,Tags=[{Key=KubernetesCluster,Value=joatmon08.k8s.local}]'" 55 | 56 | desc "Let's add the new volume ID to the pv.yaml and create it." 57 | desc "!!!! BE SURE TO ADD THE AWS REGION AND VOLUME ID TO THE pv.yaml FILE !!!!" 58 | run "kubectl apply -f pv.yaml" 59 | 60 | desc "Let's apply the pv claim." 61 | run "kubectl apply -f pv-claim.yaml" 62 | 63 | desc "We'll delete the old pvc and pv." 64 | run "kubectl delete pvc ${pvc}" 65 | run "kubectl delete pv ${volume}" 66 | 67 | desc "Let's create the StatefulSet." 68 | run "kubectl apply -f statefulset-restore.yaml" 69 | 70 | desc "Does it show the original state?" 71 | run "kubectl exec ${pod} -- cat /usr/share/hello/stateful.log" 72 | desc "YES!" 73 | 74 | desc "Let's delete everything now." 75 | run "kubectl delete -f statefulset.yaml --ignore-not-found" 76 | run "kubectl delete -f statefulset-restore.yaml --ignore-not-found" 77 | run "kubectl delete -f pv.yaml --ignore-not-found" 78 | run "kubectl delete -f pv-claim.yaml --ignore-not-found" 79 | -------------------------------------------------------------------------------- /persistent-volume/minikube/demo.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | . ../util.sh 3 | 4 | desc "Create the StatefulSet." 5 | run "kubectl apply -f statefulset.yaml" 6 | 7 | volume=$(kubectl get pvc | grep www | tail -n 1 | cut -d' ' -f9) 8 | minikube_ip=$(minikube ip) 9 | token=$(kubectl describe secret $(kubectl get secrets | grep default | cut -f1 -d ' ') | grep -E '^token' | cut -f2 -d':' | xargs) 10 | 11 | desc "Put some text for nginx to serve." 12 | run "ssh -i ~/.minikube/machines/minikube/id_rsa docker@${minikube_ip} sudo 'echo Hello! > /tmp/hostpath-provisioner/"${volume}"/index.html'" 13 | 14 | desc "Let's make a call to the nginx web server." 15 | run "curl -k -H 'Authorization:Bearer ${token}' https://${minikube_ip}:8443/api/v1/namespaces/default/services/nginx:web/proxy/" 16 | 17 | desc "Delete the StatefulSet." 18 | run "kubectl delete -f statefulset.yaml --ignore-not-found" 19 | 20 | desc "Does the volume and claim still exist?" 21 | run "kubectl get pv" 22 | run "kubectl get pvc" 23 | run "kubectl get statefulsets" 24 | run "ssh -i ~/.minikube/machines/minikube/id_rsa docker@${minikube_ip} cat /tmp/hostpath-provisioner/${volume}/index.html" 25 | desc "Yes, the volume and claim still exist!" 26 | 27 | desc "Let's bring the StatefulSet back up." 28 | run "kubectl apply -f statefulset.yaml" 29 | 30 | desc "Does the volume get reattached?" 31 | desc "Let's make a call to the nginx web server." 32 | run "curl -k -H 'Authorization:Bearer ${token}' https://${minikube_ip}:8443/api/v1/namespaces/default/services/nginx:web/proxy/" 33 | desc "Yes, the volume is reattached." 34 | 35 | desc "We'll back up the volume." 36 | run "ssh -i ~/.minikube/machines/minikube/id_rsa docker@${minikube_ip} sudo cp -r /tmp/hostpath-provisioner/${volume} /tmp/${volume}-backup" 37 | 38 | desc "Let's delete the backend volume, as if something went wrong." 39 | run "ssh -i ~/.minikube/machines/minikube/id_rsa docker@${minikube_ip} sudo rm -rf /tmp/hostpath-provisioner/${volume}" 40 | 41 | desc "Let's make a call to the nginx web server." 42 | run "curl -k -H 'Authorization:Bearer ${token}' https://${minikube_ip}:8443/api/v1/namespaces/default/services/nginx:web/proxy/" 43 | 44 | desc "Oh no!" 45 | run "kubectl get pvc" 46 | run "kubectl get pv" 47 | 48 | desc "But yet the pvc and pv are still there..." 49 | desc "Let's get more details on the actual persistent volume." 50 | desc "Notice the HostPath that is specified." 51 | run "kubectl describe pv ${volume}" 52 | 53 | desc "There's a possibility that we can still fix the volume." 54 | desc "Let's restore the volume, with our original index.html." 55 | run "ssh -i ~/.minikube/machines/minikube/id_rsa docker@${minikube_ip} sudo cp -r /tmp/${volume}-backup /tmp/hostpath-provisioner/${volume}" 56 | 57 | desc "The permissions need to be read/write/execute." 58 | run "ssh -i ~/.minikube/machines/minikube/id_rsa docker@${minikube_ip} sudo chmod 777 /tmp/hostpath-provisioner/${volume}" 59 | 60 | desc "Just in case, we'll check the claim and the volume." 61 | run "kubectl get pvc" 62 | run "kubectl get pv" 63 | 64 | desc "Let's make a call to the nginx web server." 65 | run "curl -k -H 'Authorization:Bearer ${token}' https://${minikube_ip}:8443/api/v1/namespaces/default/services/nginx:web/proxy/" 66 | 67 | desc "Interesting, it didn't work. Maybe the pod needs to be restarted?" 68 | run "kubectl delete pod web-0" 69 | 70 | desc "Let's check if the pod came back up." 71 | run "kubectl get pods" 72 | 73 | desc "Let's make a call to the nginx web server." 74 | run "curl -k -H 'Authorization:Bearer ${token}' https://${minikube_ip}:8443/api/v1/namespaces/default/services/nginx:web/proxy/" 75 | 76 | desc "Let's delete everything now." 77 | run "kubectl delete -f statefulset.yaml --ignore-not-found" 78 | run "kubectl delete pv ${volume}" 79 | run "kubectl delete pvc $(kubectl get pvc | grep web | cut -d' ' -f1)" --------------------------------------------------------------------------------