├── Dockerfile ├── k8s ├── cluster-issuer.yaml ├── configmap-env.yaml ├── configmap-family.yaml ├── deployment.yaml ├── hpa.yaml ├── ingress.yaml ├── kind.yaml ├── metrics-server.yaml ├── mysql-service-h.yaml ├── namespaces │ ├── deployment.yaml │ └── security.yaml ├── pod.yaml ├── pv.yaml_ ├── pvc.yaml ├── replicaset.yaml ├── secret.yaml ├── service.yaml └── statefulset.yaml └── server.go /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.15 2 | COPY . . 3 | RUN go build -o server . 4 | CMD ["./server"] -------------------------------------------------------------------------------- /k8s/cluster-issuer.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1alpha2 2 | kind: ClusterIssuer 3 | metadata: 4 | name: letsencrypt 5 | namespace: cert-manager 6 | spec: 7 | acme: 8 | server: https://acme-v02.api.letsencrypt.org/directory 9 | email: wesley@schoolofnet.com 10 | privateKeySecretRef: 11 | name: letsencrypt-tls 12 | solvers: 13 | - http01: 14 | ingress: 15 | class: nginx -------------------------------------------------------------------------------- /k8s/configmap-env.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: goserver-env 5 | data: 6 | NAME: "Wesley" 7 | AGE: "36" -------------------------------------------------------------------------------- /k8s/configmap-family.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: configmap-family 5 | data: 6 | members: "Wesley, Mari, Sarah, Davi, Rebbeca, Alicia" -------------------------------------------------------------------------------- /k8s/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: goserver 5 | labels: 6 | app: goserver 7 | spec: 8 | selector: 9 | matchLabels: 10 | app: goserver 11 | replicas: 1 12 | template: 13 | metadata: 14 | labels: 15 | app: "goserver" 16 | spec: 17 | containers: 18 | - name: goserver 19 | image: "wesleywillians/hello-go:v9.6" 20 | 21 | resources: 22 | requests: 23 | cpu: "0.05" 24 | memory: 20Mi 25 | limits: 26 | cpu: "0.05" 27 | memory: 25Mi 28 | 29 | startupProbe: 30 | httpGet: 31 | path: /healthz 32 | port: 8000 33 | periodSeconds: 4 34 | failureThreshold: 30 35 | 36 | readinessProbe: 37 | httpGet: 38 | path: /healthz 39 | port: 8000 40 | periodSeconds: 3 41 | failureThreshold: 1 42 | # initialDelaySeconds: 10 43 | 44 | livenessProbe: 45 | httpGet: 46 | path: /healthz 47 | port: 8000 48 | periodSeconds: 5 49 | failureThreshold: 1 50 | timeoutSeconds: 1 51 | successThreshold: 1 52 | # initialDelaySeconds: 15 53 | 54 | envFrom: 55 | - configMapRef: 56 | name: goserver-env 57 | - secretRef: 58 | name: goserver-secret 59 | 60 | volumeMounts: 61 | - mountPath: "/go/myfamily" 62 | name: config 63 | readOnly: true 64 | - mountPath: "/go/pvc" 65 | name: goserver-volume 66 | 67 | volumes: 68 | - name: goserver-volume 69 | persistentVolumeClaim: 70 | claimName: goserver-pvc 71 | 72 | - name: config 73 | configMap: 74 | name: configmap-family 75 | items: 76 | - key: members 77 | path: "family.txt" 78 | -------------------------------------------------------------------------------- /k8s/hpa.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: autoscaling/v1 2 | kind: HorizontalPodAutoscaler 3 | metadata: 4 | name: goserver-hpa 5 | spec: 6 | scaleTargetRef: 7 | apiVersion: apps/v1 8 | name: goserver 9 | kind: Deployment 10 | minReplicas: 1 11 | maxReplicas: 30 12 | targetCPUUtilizationPercentage: 25 -------------------------------------------------------------------------------- /k8s/ingress.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1beta1 2 | kind: Ingress 3 | metadata: 4 | name: ingress-host 5 | annotations: 6 | kubernetes.io/ingress.class: "nginx" 7 | cert-manager.io/cluster-issuer: "letsencrypt" 8 | ingress.kubernetes.io/force-ssl-redirect: "true" 9 | spec: 10 | rules: 11 | - host: "ingress.fullcycle.com.br" 12 | http: 13 | paths: 14 | - pathType: Prefix 15 | path: "/admin" 16 | backend: 17 | serviceName: goserver-service 18 | servicePort: 80 19 | tls: 20 | - hosts: 21 | - "ingress.fullcycle.com.br" 22 | secretName: letsencrypt-tls 23 | -------------------------------------------------------------------------------- /k8s/kind.yaml: -------------------------------------------------------------------------------- 1 | kind: Cluster 2 | apiVersion: kind.x-k8s.io/v1alpha4 3 | 4 | nodes: 5 | - role: control-plane 6 | - role: worker 7 | - role: worker 8 | - role: worker -------------------------------------------------------------------------------- /k8s/metrics-server.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | k8s-app: metrics-server 6 | name: metrics-server 7 | namespace: kube-system 8 | --- 9 | apiVersion: rbac.authorization.k8s.io/v1 10 | kind: ClusterRole 11 | metadata: 12 | labels: 13 | k8s-app: metrics-server 14 | rbac.authorization.k8s.io/aggregate-to-admin: "true" 15 | rbac.authorization.k8s.io/aggregate-to-edit: "true" 16 | rbac.authorization.k8s.io/aggregate-to-view: "true" 17 | name: system:aggregated-metrics-reader 18 | rules: 19 | - apiGroups: 20 | - metrics.k8s.io 21 | resources: 22 | - pods 23 | - nodes 24 | verbs: 25 | - get 26 | - list 27 | - watch 28 | --- 29 | apiVersion: rbac.authorization.k8s.io/v1 30 | kind: ClusterRole 31 | metadata: 32 | labels: 33 | k8s-app: metrics-server 34 | name: system:metrics-server 35 | rules: 36 | - apiGroups: 37 | - "" 38 | resources: 39 | - pods 40 | - nodes 41 | - nodes/stats 42 | - namespaces 43 | - configmaps 44 | verbs: 45 | - get 46 | - list 47 | - watch 48 | --- 49 | apiVersion: rbac.authorization.k8s.io/v1 50 | kind: RoleBinding 51 | metadata: 52 | labels: 53 | k8s-app: metrics-server 54 | name: metrics-server-auth-reader 55 | namespace: kube-system 56 | roleRef: 57 | apiGroup: rbac.authorization.k8s.io 58 | kind: Role 59 | name: extension-apiserver-authentication-reader 60 | subjects: 61 | - kind: ServiceAccount 62 | name: metrics-server 63 | namespace: kube-system 64 | --- 65 | apiVersion: rbac.authorization.k8s.io/v1 66 | kind: ClusterRoleBinding 67 | metadata: 68 | labels: 69 | k8s-app: metrics-server 70 | name: metrics-server:system:auth-delegator 71 | roleRef: 72 | apiGroup: rbac.authorization.k8s.io 73 | kind: ClusterRole 74 | name: system:auth-delegator 75 | subjects: 76 | - kind: ServiceAccount 77 | name: metrics-server 78 | namespace: kube-system 79 | --- 80 | apiVersion: rbac.authorization.k8s.io/v1 81 | kind: ClusterRoleBinding 82 | metadata: 83 | labels: 84 | k8s-app: metrics-server 85 | name: system:metrics-server 86 | roleRef: 87 | apiGroup: rbac.authorization.k8s.io 88 | kind: ClusterRole 89 | name: system:metrics-server 90 | subjects: 91 | - kind: ServiceAccount 92 | name: metrics-server 93 | namespace: kube-system 94 | --- 95 | apiVersion: v1 96 | kind: Service 97 | metadata: 98 | labels: 99 | k8s-app: metrics-server 100 | name: metrics-server 101 | namespace: kube-system 102 | spec: 103 | ports: 104 | - name: https 105 | port: 443 106 | protocol: TCP 107 | targetPort: https 108 | selector: 109 | k8s-app: metrics-server 110 | --- 111 | apiVersion: apps/v1 112 | kind: Deployment 113 | metadata: 114 | labels: 115 | k8s-app: metrics-server 116 | name: metrics-server 117 | namespace: kube-system 118 | spec: 119 | selector: 120 | matchLabels: 121 | k8s-app: metrics-server 122 | strategy: 123 | rollingUpdate: 124 | maxUnavailable: 0 125 | template: 126 | metadata: 127 | labels: 128 | k8s-app: metrics-server 129 | spec: 130 | containers: 131 | - args: 132 | - --cert-dir=/tmp 133 | - --secure-port=4443 134 | - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname 135 | - --kubelet-use-node-status-port 136 | - --kubelet-insecure-tls 137 | image: k8s.gcr.io/metrics-server/metrics-server:v0.4.1 138 | imagePullPolicy: IfNotPresent 139 | livenessProbe: 140 | failureThreshold: 3 141 | httpGet: 142 | path: /livez 143 | port: https 144 | scheme: HTTPS 145 | periodSeconds: 10 146 | name: metrics-server 147 | ports: 148 | - containerPort: 4443 149 | name: https 150 | protocol: TCP 151 | readinessProbe: 152 | failureThreshold: 3 153 | httpGet: 154 | path: /readyz 155 | port: https 156 | scheme: HTTPS 157 | periodSeconds: 10 158 | securityContext: 159 | readOnlyRootFilesystem: true 160 | runAsNonRoot: true 161 | runAsUser: 1000 162 | volumeMounts: 163 | - mountPath: /tmp 164 | name: tmp-dir 165 | nodeSelector: 166 | kubernetes.io/os: linux 167 | priorityClassName: system-cluster-critical 168 | serviceAccountName: metrics-server 169 | volumes: 170 | - emptyDir: {} 171 | name: tmp-dir 172 | --- 173 | apiVersion: apiregistration.k8s.io/v1 174 | kind: APIService 175 | metadata: 176 | labels: 177 | k8s-app: metrics-server 178 | name: v1beta1.metrics.k8s.io 179 | spec: 180 | group: metrics.k8s.io 181 | groupPriorityMinimum: 100 182 | insecureSkipTLSVerify: true 183 | service: 184 | name: metrics-server 185 | namespace: kube-system 186 | version: v1beta1 187 | versionPriority: 100 188 | -------------------------------------------------------------------------------- /k8s/mysql-service-h.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: mysql-h 5 | spec: 6 | selector: 7 | app: mysql 8 | ports: 9 | - port: 3306 10 | clusterIP: None -------------------------------------------------------------------------------- /k8s/namespaces/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: server 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: server 9 | template: 10 | metadata: 11 | labels: 12 | app: server 13 | spec: 14 | serviceAccount: server 15 | containers: 16 | - name: server 17 | image: wesleywillians/hello-express 18 | resources: 19 | limits: 20 | memory: "128Mi" 21 | cpu: "500m" 22 | ports: 23 | - containerPort: 3000 24 | -------------------------------------------------------------------------------- /k8s/namespaces/security.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: server 5 | 6 | --- 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | name: server-read 12 | rules: 13 | - apiGroups: [""] 14 | resources: ["pods","services"] 15 | verbs: ["get","watch","list"] 16 | - apiGroups: ["apps"] 17 | resources: ["deployments"] 18 | verbs: ["get","watch","list"] 19 | 20 | --- 21 | 22 | apiVersion: rbac.authorization.k8s.io/v1 23 | kind: ClusterRoleBinding 24 | metadata: 25 | name: server-read-bind 26 | subjects: 27 | - kind: ServiceAccount 28 | name: server 29 | namespace: prod 30 | roleRef: 31 | kind: ClusterRole 32 | name: server-read 33 | apiGroup: rbac.authorization.k8s.io -------------------------------------------------------------------------------- /k8s/pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "goserver" 5 | labels: 6 | app: "goserver" 7 | spec: 8 | containers: 9 | - name: goserver 10 | image: "wesleywillians/hello-go:latest" -------------------------------------------------------------------------------- /k8s/pv.yaml_: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolume 3 | metadata: 4 | name: pv1 5 | spec: 6 | capacity: 7 | storage: 50Gi 8 | accessModes: 9 | - ReadWriteOnce 10 | - ReadWriteMany -------------------------------------------------------------------------------- /k8s/pvc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: goserver-pvc 5 | spec: 6 | accessModes: 7 | - ReadWriteOnce 8 | resources: 9 | requests: 10 | storage: 5Gi -------------------------------------------------------------------------------- /k8s/replicaset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: ReplicaSet 3 | metadata: 4 | name: goserver 5 | labels: 6 | app: goserver 7 | spec: 8 | selector: 9 | matchLabels: 10 | app: goserver 11 | replicas: 10 12 | template: 13 | metadata: 14 | labels: 15 | app: "goserver" 16 | spec: 17 | containers: 18 | - name: goserver 19 | image: "wesleywillians/hello-go:v2" -------------------------------------------------------------------------------- /k8s/secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: goserver-secret 5 | type: Opaque 6 | data: 7 | USER: "d2VzbGV5Cg==" 8 | PASSWORD: "MTIzNDU2Cg==" -------------------------------------------------------------------------------- /k8s/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: goserver-service 5 | spec: 6 | selector: 7 | app: goserver 8 | type: ClusterIP 9 | ports: 10 | - name: goserver-service 11 | port: 80 12 | targetPort: 8000 13 | protocol: TCP -------------------------------------------------------------------------------- /k8s/statefulset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: mysql 5 | spec: 6 | replicas: 4 7 | serviceName: mysql-h 8 | selector: 9 | matchLabels: 10 | app: mysql 11 | template: 12 | metadata: 13 | labels: 14 | app: mysql 15 | spec: 16 | containers: 17 | - name: mysql 18 | image: mysql 19 | env: 20 | - name: MYSQL_ROOT_PASSWORD 21 | value: root 22 | volumeMounts: 23 | - mountPath: /var/lib/mysql 24 | name: mysql-volume 25 | 26 | volumeClaimTemplates: 27 | - metadata: 28 | name: mysql-volume 29 | spec: 30 | accessModes: 31 | - ReadWriteOnce 32 | resources: 33 | requests: 34 | storage: 5Gi -------------------------------------------------------------------------------- /server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "log" 7 | "net/http" 8 | "os" 9 | "time" 10 | ) 11 | 12 | var startedAt = time.Now() 13 | 14 | func main() { 15 | http.HandleFunc("/healthz", Healthz) 16 | http.HandleFunc("/secret", Secret) 17 | http.HandleFunc("/configmap", ConfigMap) 18 | http.HandleFunc("/", Hello) 19 | http.ListenAndServe(":8000", nil) 20 | } 21 | 22 | func Hello(w http.ResponseWriter, r *http.Request) { 23 | name := os.Getenv("NAME") 24 | age := os.Getenv("AGE") 25 | fmt.Fprintf(w, "Hello, I'm %s. I'm %s.", name, age) 26 | } 27 | 28 | func Secret(w http.ResponseWriter, r *http.Request) { 29 | user := os.Getenv("USER") 30 | password := os.Getenv("PASSWORD") 31 | fmt.Fprintf(w, "User: %s. Password: %s", user, password) 32 | } 33 | 34 | func ConfigMap(w http.ResponseWriter, r *http.Request) { 35 | data, err := ioutil.ReadFile("/go/myfamily/family.txt") 36 | if err != nil { 37 | log.Fatalf("Error reading file: ", err) 38 | } 39 | fmt.Fprintf(w, "My Family: %s.", string(data)) 40 | } 41 | 42 | func Healthz(w http.ResponseWriter, r *http.Request) { 43 | 44 | duration := time.Since(startedAt) 45 | 46 | if duration.Seconds() < 10 { 47 | w.WriteHeader(500) 48 | w.Write([]byte(fmt.Sprintf("Duration: %v", duration.Seconds()))) 49 | } else { 50 | w.WriteHeader(200) 51 | w.Write([]byte("ok")) 52 | } 53 | 54 | } 55 | --------------------------------------------------------------------------------