├── ServiceAccount.yaml ├── Claim.yaml ├── StorageClass.yaml ├── phpmyadmin.yaml ├── ClusterRole.yaml ├── README.md ├── WordPress.yaml ├── Deployment.yaml └── galera-cluster.yaml /ServiceAccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: nfs-provisioner -------------------------------------------------------------------------------- /Claim.yaml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: www-nfs 5 | annotations: 6 | volume.beta.kubernetes.io/storage-class: "example-nfs" 7 | spec: 8 | accessModes: 9 | - ReadWriteMany 10 | resources: 11 | requests: 12 | storage: 20Gi -------------------------------------------------------------------------------- /StorageClass.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 2 | kind: StorageClass 3 | metadata: 4 | annotations: 5 | kubectl.kubernetes.io/last-applied-configuration: | 6 | { 7 | "apiVersion":"storage.k8s.io/v1beta1", 8 | "kind":"StorageClass", 9 | "metadata":{ 10 | "annotations":{}, 11 | "name":"example-nfs", 12 | "namespace":"" 13 | }, 14 | "provisioner":"example.com/nfs" 15 | } 16 | creationTimestamp: null 17 | name: example-nfs 18 | selfLink: /apis/storage.k8s.io/v1/storageclasses/example-nfs 19 | provisioner: example.com/nfs 20 | reclaimPolicy: Retain 21 | parameters: 22 | mountOptions: "vers=4.1" 23 | -------------------------------------------------------------------------------- /phpmyadmin.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: phpmyadmin 5 | spec: 6 | ports: 7 | - port: 80 8 | targetPort: 80 9 | protocol: TCP 10 | selector: 11 | app: phpmyadmin 12 | --- 13 | apiVersion: apps/v1beta2 # for versions before 1.8.0 use apps/v1beta1 14 | kind: Deployment 15 | metadata: 16 | name: phpmyadmin 17 | spec: 18 | selector: 19 | matchLabels: 20 | app: phpmyadmin 21 | strategy: 22 | type: Recreate 23 | template: 24 | metadata: 25 | labels: 26 | app: myadmin 27 | spec: 28 | containers: 29 | - name: phpmyadmin 30 | image: phpmyadmin/phpmyadmin:edge-4.8 #@sha256:95b005cf4c5f15ff670a31f576a50db8d164c6692752bda6176af3fea0e60812 31 | ports: 32 | - containerPort: 80 33 | env: 34 | - name: PMA_HOST 35 | value: galera-db 36 | 37 | -------------------------------------------------------------------------------- /ClusterRole.yaml: -------------------------------------------------------------------------------- 1 | kind: ClusterRole 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | metadata: 4 | name: nfs-provisioner-runner 5 | rules: 6 | - apiGroups: [""] 7 | resources: ["persistentvolumes"] 8 | verbs: ["get", "list", "watch", "create", "delete"] 9 | - apiGroups: [""] 10 | resources: ["persistentvolumeclaims"] 11 | verbs: ["get", "list", "watch", "update"] 12 | - apiGroups: ["storage.k8s.io"] 13 | resources: ["storageclasses"] 14 | verbs: ["get", "list", "watch"] 15 | - apiGroups: [""] 16 | resources: ["events"] 17 | verbs: ["list", "watch", "create", "update", "patch"] 18 | - apiGroups: [""] 19 | resources: ["services", "endpoints"] 20 | verbs: ["get"] 21 | - apiGroups: ["extensions"] 22 | resources: ["podsecuritypolicies"] 23 | resourceNames: ["nfs-provisioner"] 24 | verbs: ["use"] 25 | --- 26 | kind: ClusterRoleBinding 27 | apiVersion: rbac.authorization.k8s.io/v1 28 | metadata: 29 | name: run-nfs-provisioner 30 | subjects: 31 | - kind: ServiceAccount 32 | name: nfs-provisioner 33 | namespace: default 34 | roleRef: 35 | kind: ClusterRole 36 | name: nfs-provisioner-runner 37 | apiGroup: rbac.authorization.k8s.io -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # k9s-beer-talk 2 | Kubeernetes Beer Talk Demo by [DomeCloud](https://dome.cloud) 3 | 4 | Video on Facebook [LiveTube / Live! Kubeernetes 5 | ](https://www.facebook.com/livetubethailand/videos/2061413037459464/) 6 | 7 | --- 8 | ## NFS Dynamic Provisioning 9 | 10 | Create ClusterRole and ClusterRoleBinding 11 | 12 | ``` 13 | kubectl apply -f ClusterRole.yaml 14 | ``` 15 | 16 | Create ServiceAccount 17 | 18 | ``` 19 | kubectl apply -f ServiceAccount.yaml 20 | ``` 21 | 22 | Deploy NFS Provisioner 23 | 24 | ``` 25 | kubectl apply -f Deployment.yaml 26 | ``` 27 | 28 | Create StorageClass 29 | 30 | ``` 31 | kubectl apply -f StorageClass.yaml 32 | ``` 33 | 34 | Claim Volume 35 | 36 | ``` 37 | kubectl apply -f Claim.yaml 38 | ``` 39 | 40 | --- 41 | 42 | ## MySQL Cluster 43 | 44 | ``` 45 | kubectl apply -f galera-cluster.yaml 46 | ``` 47 | 48 | ## WordPress on K8S 49 | 50 | ``` 51 | kubectl apply -f WordPress.yaml 52 | ``` 53 | 54 | ## Monitoring K8S 55 | 56 | Monitoring Kubernetes clusters on AWS, GCP and Azure using Prometheus Operator and Grafana [camilb/prometheus-kubernetes](https://github.com/camilb/prometheus-kubernetes) 57 | 58 | ``` 59 | git clone https://github.com/camilb/prometheus-kubernetes.git 60 | cd prometheus-kubernetes 61 | ./deploy 62 | ``` 63 | 64 | ## Alerting 65 | 66 | Demo 67 | -------------------------------------------------------------------------------- /WordPress.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: wp-web 5 | labels: 6 | app: wp-web 7 | spec: 8 | ports: 9 | - port: 80 10 | targetPort: 80 11 | nodePort: 30180 12 | selector: 13 | app: wp-web 14 | tier: frontend 15 | type: NodePort 16 | --- 17 | apiVersion: extensions/v1beta1 18 | kind: Deployment 19 | metadata: 20 | name: wp-web 21 | labels: 22 | app: wp-web 23 | spec: 24 | replicas: 2 25 | strategy: 26 | type: Recreate 27 | template: 28 | metadata: 29 | labels: 30 | app: wp-web 31 | tier: frontend 32 | spec: 33 | containers: 34 | - image: dome/wp 35 | name: wordpress 36 | env: 37 | - name: WORDPRESS_DB_HOST 38 | value: galera-db 39 | - name: WORDPRESS_DB_NAME 40 | value: wp_web_db 41 | - name: WORDPRESS_DB_USER 42 | value: root 43 | - name: WORDPRESS_DB_PASSWORD 44 | valueFrom: 45 | secretKeyRef: 46 | name: mysql-db 47 | key: password 48 | ports: 49 | - containerPort: 80 50 | name: wp-web 51 | volumeMounts: 52 | - name: wordpress-local-storage 53 | mountPath: /DATA 54 | imagePullPolicy: Always 55 | volumes: 56 | - name: wordpress-local-storage 57 | persistentVolumeClaim: 58 | claimName: www-nfs -------------------------------------------------------------------------------- /Deployment.yaml: -------------------------------------------------------------------------------- 1 | kind: Service 2 | apiVersion: v1 3 | metadata: 4 | name: nfs-provisioner 5 | labels: 6 | app: nfs-provisioner 7 | spec: 8 | ports: 9 | - name: nfs 10 | port: 2049 11 | - name: mountd 12 | port: 20048 13 | - name: rpcbind 14 | port: 111 15 | - name: rpcbind-udp 16 | port: 111 17 | protocol: UDP 18 | selector: 19 | app: nfs-provisioner 20 | --- 21 | kind: Deployment 22 | apiVersion: extensions/v1beta1 23 | metadata: 24 | name: nfs-provisioner 25 | spec: 26 | replicas: 1 27 | strategy: 28 | type: Recreate 29 | template: 30 | metadata: 31 | labels: 32 | app: nfs-provisioner 33 | spec: 34 | serviceAccount: nfs-provisioner 35 | nodeSelector: 36 | storagenode: nfs 37 | containers: 38 | - name: nfs-provisioner 39 | image: quay.io/kubernetes_incubator/nfs-provisioner:v1.1.0-k8s1.10 40 | ports: 41 | - name: nfs 42 | containerPort: 2049 43 | - name: mountd 44 | containerPort: 20048 45 | - name: rpcbind 46 | containerPort: 111 47 | - name: rpcbind-udp 48 | containerPort: 111 49 | protocol: UDP 50 | securityContext: 51 | capabilities: 52 | add: 53 | - DAC_READ_SEARCH 54 | - SYS_RESOURCE 55 | args: 56 | - "-provisioner=example.com/nfs" 57 | env: 58 | - name: POD_IP 59 | valueFrom: 60 | fieldRef: 61 | fieldPath: status.podIP 62 | - name: SERVICE_NAME 63 | value: nfs-provisioner 64 | - name: POD_NAMESPACE 65 | valueFrom: 66 | fieldRef: 67 | fieldPath: metadata.namespace 68 | imagePullPolicy: "IfNotPresent" 69 | volumeMounts: 70 | - name: export-volume 71 | mountPath: /export 72 | volumes: 73 | - name: export-volume 74 | hostPath: 75 | path: /data/nfs 76 | -------------------------------------------------------------------------------- /galera-cluster.yaml: -------------------------------------------------------------------------------- 1 | # A headless service to create DNS records 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | annotations: 6 | service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" 7 | name: galera-db 8 | labels: 9 | app: mysql-db 10 | spec: 11 | ports: 12 | - port: 3306 13 | name: mysql-db 14 | # *.galear.default.svc.cluster.local 15 | clusterIP: None 16 | selector: 17 | app: mysql-db 18 | --- 19 | apiVersion: v1 20 | kind: Secret 21 | metadata: 22 | name: mysql-db 23 | type: Opaque 24 | data: 25 | # Root password (base64): 123456 # echo -n '123456' | base64 26 | password: MTIzNDU2 27 | --- 28 | apiVersion: v1 29 | kind: ConfigMap 30 | metadata: 31 | name: mysql-config-voldb 32 | data: 33 | galera.cnf: | 34 | [mysqld] 35 | user = mysql 36 | bind-address = 0.0.0.0 37 | wsrep_provider = /usr/lib/galera/libgalera_smm.so 38 | # TODO: is rsync the best option? 39 | wsrep_sst_method = rsync 40 | default_storage_engine = innodb 41 | binlog_format = ROW 42 | innodb_autoinc_lock_mode = 2 43 | innodb_file_per_table 44 | max_connections = 2500 45 | key-buffer-size = 32M 46 | max-allowed-packet = 16M 47 | max-connect-errors = 1000000 48 | tmp-table-size = 32M 49 | max-heap-table-size = 32M 50 | query-cache-type = 1 51 | query-cache-size = 1000M 52 | thread-cache-size = 50 53 | open-files-limit = 65535 54 | table-definition-cache = 4096 55 | table-open-cache = 50 56 | innodb-flush-method = O_DIRECT 57 | innodb-log-files-in-group = 2 58 | innodb-log-file-size = 256M 59 | innodb-flush-log-at-trx-commit = 1 60 | innodb-file-per-table = 1 61 | innodb-buffer-pool-size = 1G 62 | 63 | # By default every node is standalone 64 | wsrep_cluster_address=gcomm:// 65 | wsrep_cluster_name=galera 66 | wsrep_node_address=127.0.0.1 67 | 68 | # TODO: Enable use privileges. This doesn't work 69 | # on mysql restart, for some reason after the SST 70 | # permissions are not setup correctly. 71 | 72 | mariadb.cnf: | 73 | [client] 74 | default-character-set = utf8 75 | [mysqld] 76 | character-set-server = utf8 77 | collation-server = utf8_general_ci 78 | # InnoDB tuning 79 | --- 80 | apiVersion: apps/v1 81 | kind: StatefulSet 82 | metadata: 83 | name: mysql-db 84 | spec: 85 | serviceName: "galera-db" 86 | replicas: 3 87 | selector: 88 | matchLabels: 89 | app: mysql-db 90 | template: 91 | metadata: 92 | labels: 93 | app: mysql-db 94 | spec: 95 | nodeSelector: # kubectl label nodes kube-2 nodedb=mysql 96 | nodedb: mysql # kubectl get nodes --show-labels 97 | affinity: 98 | podAntiAffinity: 99 | requiredDuringSchedulingIgnoredDuringExecution: 100 | - labelSelector: 101 | matchExpressions: 102 | - key: "app" 103 | operator: In 104 | values: 105 | - mysql-db 106 | topologyKey: "kubernetes.io/hostname" 107 | initContainers: 108 | - name: install 109 | image: dome/galera-install 110 | imagePullPolicy: Always 111 | args: 112 | - "--work-dir=/work-dir" 113 | volumeMounts: 114 | - name: workdir 115 | mountPath: "/work-dir" 116 | - name: config 117 | mountPath: "/etc/mysql" 118 | - name: tmp-config 119 | mountPath: /tmp 120 | - name: bootstrap 121 | image: debian:jessie 122 | command: 123 | - "/work-dir/peer-finder" 124 | args: 125 | - -on-start="/work-dir/on-start.sh" 126 | - "-service=galera-db" 127 | env: 128 | - name: POD_NAMESPACE 129 | valueFrom: 130 | fieldRef: 131 | apiVersion: v1 132 | fieldPath: metadata.namespace 133 | volumeMounts: 134 | - name: workdir 135 | mountPath: "/work-dir" 136 | - name: config 137 | mountPath: "/etc/mysql" 138 | containers: 139 | - name: mysql 140 | image: k8s.gcr.io/mysql-galera:e2e 141 | ports: 142 | - containerPort: 3306 143 | name: mysql 144 | - containerPort: 4444 145 | name: sst 146 | - containerPort: 4567 147 | name: replication 148 | - containerPort: 4568 149 | name: ist 150 | env: 151 | - name: MYSQL_ROOT_PASSWORD 152 | valueFrom: 153 | secretKeyRef: 154 | name: mysql-db 155 | key: password 156 | args: 157 | - --defaults-file=/etc/mysql/my-galera.cnf 158 | - --user=root 159 | readinessProbe: 160 | exec: 161 | command: ["bash", "-c", "mysql -uroot -p\"${MYSQL_ROOT_PASSWORD}\" -e 'show databases;'"] 162 | initialDelaySeconds: 20 163 | timeoutSeconds: 5 164 | successThreshold: 2 165 | volumeMounts: 166 | - name: datadir 167 | mountPath: /var/lib/ 168 | - name: config 169 | mountPath: /etc/mysql 170 | volumes: 171 | - name: datadir 172 | hostPath: 173 | path: /data/galera 174 | type: Directory 175 | - name: config 176 | emptyDir: {} 177 | - name: workdir 178 | emptyDir: {} 179 | - name: tmp-config 180 | configMap: 181 | name: mysql-config-voldb 182 | items: 183 | - path: "my-galera.cnf" 184 | key: galera.cnf 185 | - path: "mariadb.cnf" 186 | key: mariadb.cnf --------------------------------------------------------------------------------