From 4d02dbe534763b8abc2f42dccda391155a2794cf Mon Sep 17 00:00:00 2001 From: marcel-dempers Date: Sun, 20 Feb 2022 18:07:05 +1100 Subject: [PATCH 01/10] example-app --- .gitignore | 1 + .../example-application/configmap.yaml | 10 +++++ .../example-application/deployment.yaml | 43 +++++++++++++++++++ .../example-application/ingress.yaml | 17 ++++++++ .../example-application/service.yaml | 15 +++++++ 5 files changed, 86 insertions(+) create mode 100644 kubernetes/portainer/example-application/configmap.yaml create mode 100644 kubernetes/portainer/example-application/deployment.yaml create mode 100644 kubernetes/portainer/example-application/ingress.yaml create mode 100644 kubernetes/portainer/example-application/service.yaml diff --git a/.gitignore b/.gitignore index 05f0edd..e76baf6 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ __pycache__/ security/letsencrypt/introduction/certs/** kubernetes/shipa/installs/shipa-helm-chart-1.1.1/ messaging/kafka/data/* +kubernetes/portainer/volume* diff --git a/kubernetes/portainer/example-application/configmap.yaml b/kubernetes/portainer/example-application/configmap.yaml new file mode 100644 index 0000000..e9e3124 --- /dev/null +++ b/kubernetes/portainer/example-application/configmap.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: example-config +data: + config.json: | + { + "environment" : "dev" + } +# kubectl create configmap example-config --from-file ./golang/configs/config.json diff --git a/kubernetes/portainer/example-application/deployment.yaml b/kubernetes/portainer/example-application/deployment.yaml new file mode 100644 index 0000000..b66f5d1 --- /dev/null +++ b/kubernetes/portainer/example-application/deployment.yaml @@ -0,0 +1,43 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: example-deploy + labels: + app: example-app + test: test +spec: + selector: + matchLabels: + app: example-app + replicas: 2 + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + template: + metadata: + labels: + app: example-app + spec: + containers: + - name: example-app + image: aimvector/python:1.0.3 + imagePullPolicy: Always + ports: + - containerPort: 5000 + resources: + requests: + memory: "64Mi" + cpu: "50m" + limits: + memory: "256Mi" + cpu: "500m" + volumeMounts: + - name: config-volume + mountPath: /configs/ + volumes: + - name: config-volume + configMap: + name: example-config diff --git a/kubernetes/portainer/example-application/ingress.yaml b/kubernetes/portainer/example-application/ingress.yaml new file mode 100644 index 0000000..1b49a62 --- /dev/null +++ b/kubernetes/portainer/example-application/ingress.yaml @@ -0,0 +1,17 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: example-ingress +spec: + ingressClassName: nginx + rules: + - host: marcel.test + http: + paths: + - path: /hello + pathType: Prefix + backend: + service: + name: example-service + port: + number: 80 \ No newline at end of file diff --git a/kubernetes/portainer/example-application/service.yaml b/kubernetes/portainer/example-application/service.yaml new file mode 100644 index 0000000..7302b6d --- /dev/null +++ b/kubernetes/portainer/example-application/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: example-service + labels: + app: example-app +spec: + type: ClusterIP + selector: + app: example-app + ports: + - protocol: TCP + name: http + port: 80 + targetPort: 5000 \ No newline at end of file From a8ba3bba7c697727d41e4965f28717950f8484a0 Mon Sep 17 00:00:00 2001 From: marcel-dempers Date: Sun, 20 Feb 2022 18:21:24 +1100 Subject: [PATCH 02/10] ingress update --- kubernetes/portainer/example-application/ingress.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kubernetes/portainer/example-application/ingress.yaml b/kubernetes/portainer/example-application/ingress.yaml index 1b49a62..7b36be0 100644 --- a/kubernetes/portainer/example-application/ingress.yaml +++ b/kubernetes/portainer/example-application/ingress.yaml @@ -2,13 +2,15 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: ingressClassName: nginx rules: - host: marcel.test http: paths: - - path: /hello + - path: /hello(/|$)(.*) pathType: Prefix backend: service: From 5481fb7c46ff92f704a11f3fa1ed1f1a92fdf7a8 Mon Sep 17 00:00:00 2001 From: marcel-dempers Date: Sun, 20 Feb 2022 18:30:51 +1100 Subject: [PATCH 03/10] update --- kubernetes/ingress/ingress-nginx-example.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/kubernetes/ingress/ingress-nginx-example.yaml b/kubernetes/ingress/ingress-nginx-example.yaml index 4e83911..aa87f00 100644 --- a/kubernetes/ingress/ingress-nginx-example.yaml +++ b/kubernetes/ingress/ingress-nginx-example.yaml @@ -2,7 +2,6 @@ apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: annotations: - kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/rewrite-target: / #new name: example-app namespace: example-app From da8749be1068348322810496af66f7f289e83021 Mon Sep 17 00:00:00 2001 From: marcel-dempers Date: Sun, 20 Feb 2022 18:32:58 +1100 Subject: [PATCH 04/10] update --- kubernetes/ingress/ingress-nginx-example.yaml | 1 + kubernetes/portainer/example-application/ingress.yaml | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes/ingress/ingress-nginx-example.yaml b/kubernetes/ingress/ingress-nginx-example.yaml index aa87f00..4e83911 100644 --- a/kubernetes/ingress/ingress-nginx-example.yaml +++ b/kubernetes/ingress/ingress-nginx-example.yaml @@ -2,6 +2,7 @@ apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: annotations: + kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/rewrite-target: / #new name: example-app namespace: example-app diff --git a/kubernetes/portainer/example-application/ingress.yaml b/kubernetes/portainer/example-application/ingress.yaml index 7b36be0..f7fbcf8 100644 --- a/kubernetes/portainer/example-application/ingress.yaml +++ b/kubernetes/portainer/example-application/ingress.yaml @@ -5,7 +5,6 @@ metadata: annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: - ingressClassName: nginx rules: - host: marcel.test http: From 733553237350869570029d2727878c907f55e106 Mon Sep 17 00:00:00 2001 From: marcel-dempers Date: Sun, 20 Feb 2022 18:48:30 +1100 Subject: [PATCH 05/10] update --- kubernetes/portainer/example-application/ingress.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kubernetes/portainer/example-application/ingress.yaml b/kubernetes/portainer/example-application/ingress.yaml index f7fbcf8..fd4522a 100644 --- a/kubernetes/portainer/example-application/ingress.yaml +++ b/kubernetes/portainer/example-application/ingress.yaml @@ -3,13 +3,14 @@ kind: Ingress metadata: name: example-ingress annotations: - nginx.ingress.kubernetes.io/rewrite-target: /$2 + nginx.ingress.kubernetes.io/rewrite-target: / spec: + ingressClassName: nginx rules: - host: marcel.test http: paths: - - path: /hello(/|$)(.*) + - path: /hello pathType: Prefix backend: service: From a2d82e4dc440ebe9df7fe0c078947b9d63d63c5b Mon Sep 17 00:00:00 2001 From: marcel-dempers Date: Sun, 20 Feb 2022 18:49:53 +1100 Subject: [PATCH 06/10] update --- kubernetes/portainer/example-application/ingress.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kubernetes/portainer/example-application/ingress.yaml b/kubernetes/portainer/example-application/ingress.yaml index fd4522a..7b36be0 100644 --- a/kubernetes/portainer/example-application/ingress.yaml +++ b/kubernetes/portainer/example-application/ingress.yaml @@ -3,14 +3,14 @@ kind: Ingress metadata: name: example-ingress annotations: - nginx.ingress.kubernetes.io/rewrite-target: / + nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: ingressClassName: nginx rules: - host: marcel.test http: paths: - - path: /hello + - path: /hello(/|$)(.*) pathType: Prefix backend: service: From 99058f0d8984574d68fd7ac29cca5f8d2ff80602 Mon Sep 17 00:00:00 2001 From: marcel-dempers Date: Sun, 20 Feb 2022 21:36:14 +1100 Subject: [PATCH 07/10] test --- kubernetes/portainer/example-application/deployment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes/portainer/example-application/deployment.yaml b/kubernetes/portainer/example-application/deployment.yaml index b66f5d1..5f2fa7a 100644 --- a/kubernetes/portainer/example-application/deployment.yaml +++ b/kubernetes/portainer/example-application/deployment.yaml @@ -23,7 +23,7 @@ spec: spec: containers: - name: example-app - image: aimvector/python:1.0.3 + image: aimvector/python:1.0.4 imagePullPolicy: Always ports: - containerPort: 5000 From ac0e5cf053bd1c3a76be839656de70d2fe349d43 Mon Sep 17 00:00:00 2001 From: marcel-dempers Date: Sun, 20 Feb 2022 22:08:37 +1100 Subject: [PATCH 08/10] test --- kubernetes/portainer/example-application/deployment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes/portainer/example-application/deployment.yaml b/kubernetes/portainer/example-application/deployment.yaml index 5f2fa7a..b66f5d1 100644 --- a/kubernetes/portainer/example-application/deployment.yaml +++ b/kubernetes/portainer/example-application/deployment.yaml @@ -23,7 +23,7 @@ spec: spec: containers: - name: example-app - image: aimvector/python:1.0.4 + image: aimvector/python:1.0.3 imagePullPolicy: Always ports: - containerPort: 5000 From 4b42ca91c51ef3af554b36b240688081d1723d90 Mon Sep 17 00:00:00 2001 From: marcel-dempers Date: Sat, 26 Feb 2022 12:02:03 +1100 Subject: [PATCH 09/10] update --- kubernetes/portainer/example-application/deployment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes/portainer/example-application/deployment.yaml b/kubernetes/portainer/example-application/deployment.yaml index b66f5d1..5f2fa7a 100644 --- a/kubernetes/portainer/example-application/deployment.yaml +++ b/kubernetes/portainer/example-application/deployment.yaml @@ -23,7 +23,7 @@ spec: spec: containers: - name: example-app - image: aimvector/python:1.0.3 + image: aimvector/python:1.0.4 imagePullPolicy: Always ports: - containerPort: 5000 From 79052248fad591eea33a79227d72110387a5a269 Mon Sep 17 00:00:00 2001 From: marcel-dempers Date: Mon, 7 Mar 2022 22:28:16 +1100 Subject: [PATCH 10/10] portainer files --- kubernetes/portainer/README.md | 124 ++++++++++++++++++ kubernetes/portainer/kind.yaml | 12 ++ .../portainer-agent-ce211-k8s-nodeport.yaml | 81 ++++++++++++ .../portainer/portainer-agent-edge-k8s.yaml | 100 ++++++++++++++ 4 files changed, 317 insertions(+) create mode 100644 kubernetes/portainer/README.md create mode 100644 kubernetes/portainer/kind.yaml create mode 100644 kubernetes/portainer/portainer-agent-ce211-k8s-nodeport.yaml create mode 100644 kubernetes/portainer/portainer-agent-edge-k8s.yaml diff --git a/kubernetes/portainer/README.md b/kubernetes/portainer/README.md new file mode 100644 index 0000000..21e02d7 --- /dev/null +++ b/kubernetes/portainer/README.md @@ -0,0 +1,124 @@ +# Introduction to Portainer + +Start here 👉🏽[https://www.portainer.io/](https://www.portainer.io/)
+Documentation 👉🏽[https://docs.portainer.io/](https://docs.portainer.io/) + +## Portainer installation + +In this demo, I will be running Kubernetes 1.22 using `kind`
+Which is compatible with portainer 2.11.1
+ +Let's go ahead with a local docker install: + +``` +cd kubernetes\portainer +mkdir volume-ce + +docker run -d -p 9443:9443 -p 8000:8000 --name portainer-ce ` +--restart=always ` +-v /var/run/docker.sock:/var/run/docker.sock ` +-v ${PWD}/volume-ce:/data ` +portainer/portainer-ce:2.11.1 +``` + +## SSL & DOMAIN + +We can also upload SSL certificates for our portainer.
+In this demo, portainer will issue self signed certificates.
+We will need a domain for our portainer server so our clusters can contact it.
+Let's use [nip.io](https://nip.io/) to create a public endpoint for portainer. + +## Create Kubernetes Cluster + +Let's start by creating a local `kind` [cluster](https://kind.sigs.k8s.io/) + +For local clusters, we can use the public endpoint Agent.
+We can get a public endpoint for the portainer agent by:
+ +* Ingress +* LoadBalancer +* NodePort + +So we'll deploy portainer agent with `NodePort` for local
+ +For production environments, I would recommend not to expose the portainer agent.
+In this case, for Production, we'll use the portainer edge agent.
+ + +To get `NodePort` exposed in `kind`, we'll open a host port with a [kind.yaml](./kind.yaml) config + +``` +kind create cluster --name local --config kind.yaml +``` + +## Manage Kubernetes Environments + +The portainer UI gives us a one line command to deploy the portainer agent.
+Note that in the video, we pick the `node port` option. + +## Local: Portainer Agent + +I download the YAML from [here](https://downloads.portainer.io/portainer-agent-ce211-k8s-nodeport.yaml) to take a closer look at what it is deploying
+ +Deploy the portainer agent in my `kind` cluster: + +``` +kubectl apply -f portainer-agent-ce211-k8s-nodeport.yaml +``` + +See the agent: + +``` +kubectl -n portainer get pods +``` + +See the service with the endpoint it exposes: + +``` +kubectl -n portainer get svc +``` + +Now since we dont have a public load balancer and using nodeport, our service will be exposed on the node IP.
+Since the Kubernetes node is our local machine, we should be able to access the portainer agent on `:30778`
+ +We can obtain our local IP with `ipconfig`
+The IP and NodePort will be used to connect our portainer server to the new agent.
+ +## Production: Portainer Edge Agent + +For the Edge agent, we get the command in the portainer UI.
+Once deployed, we can see the egde agent in our AKS cluster: + +``` +kubectl -n portainer get pods +``` + +## Helm + +Let's showcase how to deploy helm charts.
+Most folks would have helm charts for their ingress controllers, monitoring, logging and other +platform dependencies.
+ +Let's add Kubernetes NGINX Ingress repo: + +``` +https://kubernetes.github.io/ingress-nginx +``` + +## GitOps + +So from the Application menu, we can add an application from a `git` repository.
+Let's add this repo: + +``` +https://github.com/marcel-dempers/docker-development-youtube-series +``` + +We also specify all our manifests path that portainer needs to deploy: + +* kubernetes/portainer/example-application/deployment.yaml +* kubernetes/portainer/example-application/configmap.yaml +* kubernetes/portainer/example-application/service.yaml +* kubernetes/portainer/example-application/ingress.yaml + +Portainer will now poll our repo and deploy any updates, GitOps style! diff --git a/kubernetes/portainer/kind.yaml b/kubernetes/portainer/kind.yaml new file mode 100644 index 0000000..75d4b10 --- /dev/null +++ b/kubernetes/portainer/kind.yaml @@ -0,0 +1,12 @@ +apiVersion: kind.x-k8s.io/v1alpha4 +kind: Cluster +nodes: +- role: control-plane + image: kindest/node:v1.22.0@sha256:b8bda84bb3a190e6e028b1760d277454a72267a5454b57db34437c34a588d047 + extraPortMappings: + - containerPort: 30778 + hostPort: 30778 + listenAddress: "0.0.0.0" + protocol: tcp +- role: worker + image: kindest/node:v1.22.0@sha256:b8bda84bb3a190e6e028b1760d277454a72267a5454b57db34437c34a588d047 \ No newline at end of file diff --git a/kubernetes/portainer/portainer-agent-ce211-k8s-nodeport.yaml b/kubernetes/portainer/portainer-agent-ce211-k8s-nodeport.yaml new file mode 100644 index 0000000..73802a7 --- /dev/null +++ b/kubernetes/portainer/portainer-agent-ce211-k8s-nodeport.yaml @@ -0,0 +1,81 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: portainer +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: portainer-sa-clusteradmin + namespace: portainer +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: portainer-crb-clusteradmin +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: +- kind: ServiceAccount + name: portainer-sa-clusteradmin + namespace: portainer +--- +apiVersion: v1 +kind: Service +metadata: + name: portainer-agent + namespace: portainer +spec: + type: NodePort + selector: + app: portainer-agent + ports: + - name: http + protocol: TCP + port: 9001 + targetPort: 9001 + nodePort: 30778 +--- +apiVersion: v1 +kind: Service +metadata: + name: portainer-agent-headless + namespace: portainer +spec: + clusterIP: None + selector: + app: portainer-agent +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: portainer-agent + namespace: portainer +spec: + selector: + matchLabels: + app: portainer-agent + template: + metadata: + labels: + app: portainer-agent + spec: + serviceAccountName: portainer-sa-clusteradmin + containers: + - name: portainer-agent + image: portainer/agent:2.11.1 + imagePullPolicy: Always + env: + - name: LOG_LEVEL + value: DEBUG + - name: AGENT_CLUSTER_ADDR + value: "portainer-agent-headless" + - name: KUBERNETES_POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + ports: + - containerPort: 9001 + protocol: TCP diff --git a/kubernetes/portainer/portainer-agent-edge-k8s.yaml b/kubernetes/portainer/portainer-agent-edge-k8s.yaml new file mode 100644 index 0000000..f1c9027 --- /dev/null +++ b/kubernetes/portainer/portainer-agent-edge-k8s.yaml @@ -0,0 +1,100 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: portainer +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: portainer-sa-clusteradmin + namespace: portainer +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: portainer-crb-clusteradmin +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: + - kind: ServiceAccount + name: portainer-sa-clusteradmin + namespace: portainer +# Optional: can be added to expose the agent port 80 to associate an Edge key. +# --- +# apiVersion: v1 +# kind: Service +# metadata: +# name: portainer-agent +# namespace: portainer +# spec: +# type: LoadBalancer +# selector: +# app: portainer-agent +# ports: +# - name: http +# protocol: TCP +# port: 80 +# targetPort: 80 +--- +apiVersion: v1 +kind: Service +metadata: + name: portainer-agent + namespace: portainer +spec: + clusterIP: None + selector: + app: portainer-agent +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: portainer-agent + namespace: portainer +spec: + selector: + matchLabels: + app: portainer-agent + template: + metadata: + labels: + app: portainer-agent + spec: + serviceAccountName: portainer-sa-clusteradmin + containers: + - name: portainer-agent + image: portainer/agent:2.11.1 + imagePullPolicy: Always + env: + - name: LOG_LEVEL + value: INFO + - name: KUBERNETES_POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: EDGE + value: "1" + - name: AGENT_CLUSTER_ADDR + value: "portainer-agent" + - name: EDGE_ID + valueFrom: + configMapKeyRef: + name: portainer-agent-edge + key: edge.id + - name: EDGE_INSECURE_POLL + valueFrom: + configMapKeyRef: + name: portainer-agent-edge + key: edge.insecure_poll + - name: EDGE_KEY + valueFrom: + secretKeyRef: + name: portainer-agent-edge-key + key: edge.key + ports: + - containerPort: 9001 + protocol: TCP + - containerPort: 80 + protocol: TCP