<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://leo.leung.xyz/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=136.159.160.201</id>
	<title>Leo&#039;s Notes - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://leo.leung.xyz/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=136.159.160.201"/>
	<link rel="alternate" type="text/html" href="https://leo.leung.xyz/wiki/Special:Contributions/136.159.160.201"/>
	<updated>2026-10-07T06:07:04Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>https://leo.leung.xyz/wiki/index.php?title=GitLab&amp;diff=2714</id>
		<title>GitLab</title>
		<link rel="alternate" type="text/html" href="https://leo.leung.xyz/wiki/index.php?title=GitLab&amp;diff=2714"/>
		<updated>2018-12-06T22:17:17Z</updated>

		<summary type="html">&lt;p&gt;136.159.160.201: /* Docker Registry Runners */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Docker Registry Runners ==&lt;br /&gt;
&lt;br /&gt;
* https://angristan.xyz/build-push-docker-images-gitlab-ci/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{highlight|lang=terminal|code=&lt;br /&gt;
# docker-compose run --rm gitlab-runner register -n --url https://git.steamr.com/ --registration-token z276ujRTK69qD8xb-aNH --executor docker --docker-image &amp;quot;docker:stable&amp;quot;&lt;br /&gt;
Runtime platform                                    arch=amd64 os=linux pid=7 revision=3afdaba6 version=11.5.0&lt;br /&gt;
Running in system-mode.&lt;br /&gt;
&lt;br /&gt;
Registering runner... succeeded                     runner=z276ujRT&lt;br /&gt;
Runner registered successfully. Feel free to start it, but if it&#039;s running already the config should be automatically reloaded!&lt;br /&gt;
&lt;br /&gt;
root@docker:/root/docker/running/gitlab# cat /var/volumes/gitlab/runner-config/config.toml&lt;br /&gt;
concurrent = 1&lt;br /&gt;
check_interval = 0&lt;br /&gt;
&lt;br /&gt;
[session_server]&lt;br /&gt;
  session_timeout = 1800&lt;br /&gt;
&lt;br /&gt;
[[runners]]&lt;br /&gt;
  name = &amp;quot;3b70de49f826&amp;quot;&lt;br /&gt;
  url = &amp;quot;https://git.steamr.com/&amp;quot;&lt;br /&gt;
  token = &amp;quot;1dbe4535e5aaa49d6582d374a29c28&amp;quot;&lt;br /&gt;
  executor = &amp;quot;docker&amp;quot;&lt;br /&gt;
  [runners.docker]&lt;br /&gt;
    tls_verify = false&lt;br /&gt;
    image = &amp;quot;docker:stable&amp;quot;&lt;br /&gt;
    privileged = false&lt;br /&gt;
    disable_entrypoint_overwrite = false&lt;br /&gt;
    oom_kill_disable = false&lt;br /&gt;
    disable_cache = false&lt;br /&gt;
    volumes = [&amp;quot;/cache&amp;quot;]&lt;br /&gt;
    shm_size = 0&lt;br /&gt;
  [runners.cache]&lt;br /&gt;
    [runners.cache.s3]&lt;br /&gt;
    [runners.cache.gcs]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
root@docker:/root/docker/running/gitlab# cat docker-compose.yml /root/docker/running/gitla&lt;br /&gt;
version: &#039;3.3&#039;&lt;br /&gt;
&lt;br /&gt;
services:&lt;br /&gt;
&lt;br /&gt;
  gitlab:&lt;br /&gt;
    #build:&lt;br /&gt;
    #  context: ./gogs&lt;br /&gt;
    #  dockerfile: Dockerfile&lt;br /&gt;
    # letsencrypt[&#039;enable&#039;] = false&lt;br /&gt;
    image: gitlab/gitlab-ce:latest&lt;br /&gt;
    container_name: gitlab&lt;br /&gt;
    environment:&lt;br /&gt;
      GITLAB_OMNIBUS_CONFIG: {{!}}&lt;br /&gt;
        external_url &#039;https://git.steamr.com&#039;&lt;br /&gt;
        nginx[&#039;listen_port&#039;] = &#039;80&#039;&lt;br /&gt;
        nginx[&#039;listen_https&#039;] = false&lt;br /&gt;
        nginx[&#039;proxy_set_headers&#039;] = { &#039;X-Forwarded-Proto&#039; =&amp;gt; &#039;https&#039;, &#039;X-Forwarded-Ssl&#039; =&amp;gt; &#039;on&#039; }&lt;br /&gt;
        registry_external_url &#039;https://registry.steamr.com&#039;&lt;br /&gt;
        registry[&#039;enable&#039;] = true&lt;br /&gt;
        gitlab_rails[&#039;registry_enabled&#039;] = true&lt;br /&gt;
        registry_nginx[&#039;listen_port&#039;] = 5001&lt;br /&gt;
        registry_nginx[&#039;listen_https&#039;] = false&lt;br /&gt;
        registry_nginx[&#039;proxy_set_headers&#039;] = { &#039;X-Forwarded-Proto&#039; =&amp;gt; &#039;https&#039;, &#039;X-Forwarded-Ssl&#039; =&amp;gt; &#039;on&#039; }&lt;br /&gt;
    volumes:&lt;br /&gt;
      - /var/volumes/gitlab/config:/etc/gitlab&lt;br /&gt;
      - /var/volumes/gitlab/logs:/var/log/gitlab&lt;br /&gt;
      - /var/volumes/gitlab/data:/var/opt/gitlab&lt;br /&gt;
    restart: always&lt;br /&gt;
    expose:&lt;br /&gt;
      - &amp;quot;80&amp;quot;&lt;br /&gt;
      - &amp;quot;5001&amp;quot;&lt;br /&gt;
    ports:&lt;br /&gt;
      - &amp;quot;10.1.2.54:22:22&amp;quot;&lt;br /&gt;
    labels:&lt;br /&gt;
      - &amp;quot;traefik.enable=true&amp;quot;&lt;br /&gt;
      - &amp;quot;traefik.docker.network=traefik&amp;quot;&lt;br /&gt;
      - &amp;quot;traefik.web.port=80&amp;quot;&lt;br /&gt;
      - &amp;quot;traefik.web.frontend.rule=Host:git.steamr.com&amp;quot;&lt;br /&gt;
      - &amp;quot;traefik.registry.port=5001&amp;quot;&lt;br /&gt;
      - &amp;quot;traefik.registry.frontend.rule=Host:registry.steamr.com&amp;quot;&lt;br /&gt;
    networks:&lt;br /&gt;
      - traefik&lt;br /&gt;
    healthcheck:&lt;br /&gt;
      disable: true&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  gitlab-runner:&lt;br /&gt;
    image: gitlab/gitlab-runner:latest&lt;br /&gt;
    container_name: gitlab-runner&lt;br /&gt;
    restart: always&lt;br /&gt;
    volumes:&lt;br /&gt;
      - /var/volumes/gitlab/runner-config:/etc/gitlab-runner&lt;br /&gt;
      - /var/run/docker.sock:/run/docker.sock&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
networks:&lt;br /&gt;
  traefik:&lt;br /&gt;
    external:&lt;br /&gt;
      name: traefik&lt;br /&gt;
&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>136.159.160.201</name></author>
	</entry>
	<entry>
		<id>https://leo.leung.xyz/wiki/index.php?title=Kubernetes&amp;diff=2713</id>
		<title>Kubernetes</title>
		<link rel="alternate" type="text/html" href="https://leo.leung.xyz/wiki/index.php?title=Kubernetes&amp;diff=2713"/>
		<updated>2018-12-06T22:14:43Z</updated>

		<summary type="html">&lt;p&gt;136.159.160.201: /* Namespaces */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This article goes over concepts as I try to understand everything about Kubernetes.&lt;br /&gt;
&lt;br /&gt;
== Installing ==&lt;br /&gt;
* https://www.linuxtechi.com/install-kubernetes-1-7-centos7-rhel7/&lt;br /&gt;
&lt;br /&gt;
=== Master Node ===&lt;br /&gt;
{{highlight|lang=terminal|code=&lt;br /&gt;
# firewall-cmd --permanent --add-port=6443/tcp&lt;br /&gt;
# firewall-cmd --permanent --add-port=2379-2380/tcp&lt;br /&gt;
# firewall-cmd --permanent --add-port=10250/tcp&lt;br /&gt;
# firewall-cmd --permanent --add-port=10251/tcp&lt;br /&gt;
# firewall-cmd --permanent --add-port=10252/tcp&lt;br /&gt;
# firewall-cmd --permanent --add-port=10255/tcp&lt;br /&gt;
# firewall-cmd --reload&lt;br /&gt;
## Kubernetes does not handle memory evictions, disable swap. remember to remove it from /etc/fstab too.&lt;br /&gt;
# swapoff -a&lt;br /&gt;
# cat &amp;lt;&amp;lt;EOF &amp;gt; /etc/yum.repos.d/kubernetes.repo&lt;br /&gt;
[kubernetes]&lt;br /&gt;
name=Kubernetes&lt;br /&gt;
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64&lt;br /&gt;
enabled=1&lt;br /&gt;
gpgcheck=1&lt;br /&gt;
repo_gpgcheck=1&lt;br /&gt;
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg&lt;br /&gt;
       https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg&lt;br /&gt;
EOF&lt;br /&gt;
# yum -y install kubeadm docker&lt;br /&gt;
# systemctl enable docker kubelet&lt;br /&gt;
# systemctl start docker kubelet&lt;br /&gt;
# kubeadm init&lt;br /&gt;
&lt;br /&gt;
# export kubever=$(kubectl version {{!}} base64 {{!}} tr -d &#039;\n&#039;)&lt;br /&gt;
# kubectl apply -f &amp;quot;https://cloud.weave.works/k8s/net?k8s-version=$kubever&amp;quot;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Once everything finishes running, it may take a few more minutes before the node becomes ready as the WeaveWorks network containers get pulled and started.&lt;br /&gt;
&lt;br /&gt;
==== Dashboard ====&lt;br /&gt;
To get the Web UI Dashboard working, see:&lt;br /&gt;
* https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/#deploying-the-dashboard-ui&lt;br /&gt;
* https://docs.aws.amazon.com/eks/latest/userguide/dashboard-tutorial.html&lt;br /&gt;
&lt;br /&gt;
It boils down to:&lt;br /&gt;
{{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl create -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml&lt;br /&gt;
# kubectl apply -f https://raw.githubusercontent.com/kubernetes/heapster/master/deploy/kube-config/influxdb/heapster.yaml&lt;br /&gt;
# kubectl apply -f https://raw.githubusercontent.com/kubernetes/heapster/master/deploy/kube-config/influxdb/influxdb.yaml&lt;br /&gt;
# kubectl apply -f https://raw.githubusercontent.com/kubernetes/heapster/master/deploy/kube-config/rbac/heapster-rbac.yaml&lt;br /&gt;
&lt;br /&gt;
## Create a service account with permission:&lt;br /&gt;
# cat &amp;lt;&amp;lt;EOF &amp;gt; eks-admin-service-account.yaml&lt;br /&gt;
apiVersion: v1&lt;br /&gt;
kind: ServiceAccount&lt;br /&gt;
metadata:&lt;br /&gt;
  name: eks-admin&lt;br /&gt;
  namespace: kube-system&lt;br /&gt;
EOF&lt;br /&gt;
# kubectl apply -f eks-admin-service-account.yaml&lt;br /&gt;
# cat &amp;lt;&amp;lt;EOF &amp;gt; eks-admin-cluster-role-binding.yaml&lt;br /&gt;
apiVersion: rbac.authorization.k8s.io/v1beta1&lt;br /&gt;
kind: ClusterRoleBinding&lt;br /&gt;
metadata:&lt;br /&gt;
  name: eks-admin&lt;br /&gt;
roleRef:&lt;br /&gt;
  apiGroup: rbac.authorization.k8s.io&lt;br /&gt;
  kind: ClusterRole&lt;br /&gt;
  name: cluster-admin&lt;br /&gt;
subjects:&lt;br /&gt;
- kind: ServiceAccount&lt;br /&gt;
  name: eks-admin&lt;br /&gt;
  namespace: kube-system&lt;br /&gt;
EOF&lt;br /&gt;
# kubectl apply -f eks-admin-cluster-role-binding.yaml&lt;br /&gt;
&lt;br /&gt;
## Get the access token&lt;br /&gt;
# kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep eks-admin | awk &#039;{print $1}&#039;)&lt;br /&gt;
&lt;br /&gt;
## Proxy, and then navigate to http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#!/login&lt;br /&gt;
# kubectl proxy&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Kubernetes (worker) Nodes ===&lt;br /&gt;
&lt;br /&gt;
{{highlight|lang=terminal|code=&lt;br /&gt;
# firewall-cmd --permanent --add-port=10250/tcp&lt;br /&gt;
# firewall-cmd --permanent --add-port=10255/tcp&lt;br /&gt;
# firewall-cmd --permanent --add-port=30000-32767/tcp&lt;br /&gt;
# firewall-cmd --permanent --add-port=6783/tcp&lt;br /&gt;
# firewall-cmd  --reload&lt;br /&gt;
## Kubernetes does not handle memory evictions, disable swap. remember to remove it from /etc/fstab too.&lt;br /&gt;
# swapoff -a&lt;br /&gt;
# modprobe br_netfilter&lt;br /&gt;
# for i in ip_vs ip_vs_sh ip_vs_rr ip_vs_wrr ; do modprobe $i ; done&lt;br /&gt;
&lt;br /&gt;
# cat &amp;lt;&amp;lt;EOF &amp;gt; /etc/yum.repos.d/kubernetes.repo&lt;br /&gt;
[kubernetes]&lt;br /&gt;
name=Kubernetes&lt;br /&gt;
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64&lt;br /&gt;
enabled=1&lt;br /&gt;
gpgcheck=1&lt;br /&gt;
repo_gpgcheck=1&lt;br /&gt;
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg&lt;br /&gt;
       https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
# yum -y install kubeadm docker&lt;br /&gt;
# systemctl enable docker kubelet&lt;br /&gt;
# systemctl start docker kubelet&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
To join the worker to the cluster, obtain the join token as well as the discovery token CA cert hash. On the master node, run:&lt;br /&gt;
&lt;br /&gt;
{{highlight|lang=terminal|code=&lt;br /&gt;
# openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt {{!}} openssl rsa -pubin -outform der 2&amp;gt;/dev/null {{!}} openssl dgst -sha256 -hex {{!}} sed &#039;s/^.* //&#039;&lt;br /&gt;
4c6ee8dd02afae0f9231c1002a4fca671622addc7ff4b522a70d68ed0b525445&lt;br /&gt;
# kubeadm token list&lt;br /&gt;
TOKEN                     TTL         EXPIRES                     USAGES                   DESCRIPTION                                                EXTRA GROUPS&lt;br /&gt;
a0mjyg.eiqvzbpwf2dgn9z3   &amp;lt;invalid&amp;gt;   2018-11-29T11:57:02-07:00   authentication,signing   The default bootstrap token generated by &#039;kubeadm init&#039;.   system:bootstrappers:kubeadm:default-node-token&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Based on the values above, on the worker node, run:&lt;br /&gt;
{{highlight|lang=terminal|code=&lt;br /&gt;
# kubeadm join --token a0mjyg.eiqvzbpwf2dgn9z3 --discovery-token-ca-cert-hash sha256:4c6ee8dd02afae0f9231c1002a4fca671622addc7ff4b522a70d68ed0b525445 10.1.3.252:6443&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Alternatively, you could generate a new token on the master node:&lt;br /&gt;
&lt;br /&gt;
{{highlight|lang=terminal|code=&lt;br /&gt;
# kubeadm token create --print-join-command&lt;br /&gt;
kubeadm join 10.1.3.252:6443 --token so4o6b.fyzvgwpgmpoq6mdm --discovery-token-ca-cert-hash sha256:4c6ee8dd02afae0f9231c1002a4fca671622addc7ff4b522a70d68ed0b525445&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Quick Start ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get an application running ===&lt;br /&gt;
What you want to do to get an application running as a service:&lt;br /&gt;
* Create a deployment which defines how many replicas should exist, the container to use, and exposed ports.&lt;br /&gt;
** This will create a Pod. Each replica creates an additional Pod (that ideally resides on different nodes).&lt;br /&gt;
** {{code|kubectl get deployments}} to see deployments&lt;br /&gt;
** {{code|kubectl get pods}} to see pods&lt;br /&gt;
* Create a service which defines the name of the service and the port the service is exposed on&lt;br /&gt;
** {{code|kubectl get service}}&lt;br /&gt;
&lt;br /&gt;
== Concepts ==&lt;br /&gt;
See the Kubernetes documentation at https://kubernetes.io/docs/concepts/&lt;br /&gt;
&lt;br /&gt;
In summary:&lt;br /&gt;
* A &#039;&#039;&#039;Deployment&#039;&#039;&#039; defines the desired state for pods and ReplicaSets.&lt;br /&gt;
* A &#039;&#039;&#039;ReplicaSets&#039;&#039;&#039; creates or destroys Pods (depending on scaling?).&lt;br /&gt;
* A &#039;&#039;&#039;Pod&#039;&#039;&#039; is a collection of container(s) all residing on one node.&lt;br /&gt;
* A &#039;&#039;&#039;Service&#039;&#039;&#039; is an abstraction that defines the logical set of Pods. The Pods could be turned off or migrated without affecting the overall Service.&lt;br /&gt;
* A &#039;&#039;&#039;Master Node&#039;&#039;&#039; is responsible for maintaining the state of the Kubernetes cluster.&lt;br /&gt;
* A &#039;&#039;&#039;Kubernetes (Worker) Node&#039;&#039;&#039; is responsible for running the actual applications managed by Kubernetes.&lt;br /&gt;
&lt;br /&gt;
Each concept will be covered in more detail below.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Pods ===&lt;br /&gt;
A pod is:&lt;br /&gt;
* A collection of application containers&lt;br /&gt;
* Guaranteed to land on the same kubernetes cluster machine&lt;br /&gt;
* Shares the same cgroup, IP address, hostname (hence, runs in the same execution environment)&lt;br /&gt;
&lt;br /&gt;
A pod should provide one individual component of an application that can:&lt;br /&gt;
* Be scaled independently of all other components in the application (eg. Database with respect to the frontend web server)&lt;br /&gt;
* Work even if placed (ie. orchestrated) on a different machine&lt;br /&gt;
&lt;br /&gt;
{{Quote|text=In general, the right question to ask yourself when designing Pods is, “Will these containers work correctly if they land on different machines?” If the answer is “no,” a Pod is the correct grouping for the containers. If the answer is “yes,” multiple Pods is probably the correct solution. In the example at the beginning of this chapter, the two containers interact via a local filesystem. It would be impossible for them to operate correctly if the containers were scheduled on different machines.|cite=Thinking with Pods, Kubernetes: Up and Running}}&lt;br /&gt;
&lt;br /&gt;
Pods are defined in text file as a manifest. The Kubernetes API server processes the manifest, then stores it in persistent storage (etcd). A scheduler then finds pods that need to be scheduled and deploys the pods on the appropriate resource that satisfies any constraints defined in the manifest. &lt;br /&gt;
&lt;br /&gt;
A Pod can be created by invoking a command: {{code|1=kubectl run kuard --image=registry/something/something:tag}}. However, using a manifest (aka. an object definition in yaml) to define the Pod is more manageable. A manifest looks something like this:&lt;br /&gt;
{{highlight|lang=text|&lt;br /&gt;
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2&lt;br /&gt;
kind: Pod&lt;br /&gt;
metadata:&lt;br /&gt;
  name: kuard&lt;br /&gt;
spec:&lt;br /&gt;
  containers:&lt;br /&gt;
    - image: gcr.io/kuar-demo/kuard-amd64:1&lt;br /&gt;
      name: kuard&lt;br /&gt;
      ports:&lt;br /&gt;
        - containerPort: 8080&lt;br /&gt;
          name: http&lt;br /&gt;
          protocol: TCP&lt;br /&gt;
      env:&lt;br /&gt;
        - value: something&lt;br /&gt;
      resources:&lt;br /&gt;
        requests:&lt;br /&gt;
          cpu: 100m&lt;br /&gt;
          cpu: 100Mi&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A few things to note from the definition above (and this applies to all manifests)&lt;br /&gt;
# Kind: Specifies the kind of Kubernetes resource this manifest defines&lt;br /&gt;
# Metadata: Helpful data to uniquely identify the object. Eg. name, UID, optionally namespace&lt;br /&gt;
# Spec: Object data; for Pods, it should be an array of containers (including container image, name, ports, environment variables, resources, etc).&lt;br /&gt;
For more information on the spec, see https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Create using {{code|kubectl apply -f pod-manifest.yml}}&lt;br /&gt;
* See it using {{code|kubectl get pods}}&lt;br /&gt;
* Detailed information about it using {{code|kubectl describe pods pod-name}}&lt;br /&gt;
* Delete it using {{code|kubectl delete pods/pod-name}} or {{code|kubectl delete -f pod-manifest.yml}}&lt;br /&gt;
&lt;br /&gt;
Pods that are set for deletion will cease to have new requests sent to it. After a 30 second termination grace period, the pods are then terminated. This extra time allows for the pod to reliably finish active requests.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Deployments ===&lt;br /&gt;
Deployments defines the state of Pods or ReplicaSets.&lt;br /&gt;
&lt;br /&gt;
The manifest&#039;s spec should contain a template that contains the information about a new Pod.&lt;br /&gt;
&lt;br /&gt;
Example Deployment manifest:&lt;br /&gt;
{{highlight|lang=text|text=&lt;br /&gt;
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2&lt;br /&gt;
kind: Deployment&lt;br /&gt;
metadata:&lt;br /&gt;
  name: frontend&lt;br /&gt;
  labels:&lt;br /&gt;
    app: guestbook&lt;br /&gt;
spec:&lt;br /&gt;
  selector:&lt;br /&gt;
    matchLabels:&lt;br /&gt;
      app: guestbook&lt;br /&gt;
      tier: frontend&lt;br /&gt;
  replicas: 3&lt;br /&gt;
  template:&lt;br /&gt;
    *** Pod&#039;s metadata and spec ***&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
* Create using {{code|kubectl apply -f frontend-deployment.yml}}&lt;br /&gt;
* See it using {{code|kubectl get deployments}}&lt;br /&gt;
* Pods that this deployment creates can be seen using the label selector.&lt;br /&gt;
** This example manifest has 2 labels applied: app, and tier&lt;br /&gt;
** See it using {{code|1=kubectl get pods -l app=guestbook -l tier=frontend}}&lt;br /&gt;
&lt;br /&gt;
You can change the scale of a deployment:&lt;br /&gt;
{{highlight|lang=terminal|code=&lt;br /&gt;
[root@kube guestbook]# kubectl get deployment frontend&lt;br /&gt;
NAME       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE&lt;br /&gt;
frontend   3         3         3            3           44m&lt;br /&gt;
[root@kube guestbook]# kubectl scale deployment frontend --replicas=5&lt;br /&gt;
deployment.extensions/frontend scaled&lt;br /&gt;
[root@kube guestbook]# kubectl get deployment frontend&lt;br /&gt;
NAME       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE&lt;br /&gt;
frontend   5         5         5            5           45m&lt;br /&gt;
[root@kube guestbook]# kubectl get pods&lt;br /&gt;
NAME                            READY   STATUS    RESTARTS   AGE&lt;br /&gt;
frontend-654c699bc8-5ngzj       1/1     Running   0          45m&lt;br /&gt;
frontend-654c699bc8-77b58       1/1     Running   0          45m&lt;br /&gt;
frontend-654c699bc8-ll7cr       1/1     Running   0          22s&lt;br /&gt;
frontend-654c699bc8-pqzvp       1/1     Running   0          22s&lt;br /&gt;
frontend-654c699bc8-sq682       1/1     Running   0          45m&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Service ===&lt;br /&gt;
An application may depend on a service that is provided by one or more Pods. While it is possible to hard code the Pod&#039;s IP address, it is better to abstract these Pod&#039;s services as a Pod&#039;s Service which can be discovered (via Service Discovery). In addition, Pods providing the Service could be migrated, turned off, or scaled up without affecting the Service&#039;s availability (as the Service can automatically route traffic to available Pods).&lt;br /&gt;
&lt;br /&gt;
A Service by default provides a single IP address for the set of pods (known as a ClusterIP) and are only accessible within the cluster. This can be changed so that a Service provides a load balanced port (LoadBalancer) or a port which is exposed on the node (NodePort).&lt;br /&gt;
&lt;br /&gt;
An example manifest:&lt;br /&gt;
{{highlight|lang=terminal|code=&lt;br /&gt;
apiVersion: v1&lt;br /&gt;
kind: Service&lt;br /&gt;
metadata:&lt;br /&gt;
  name: frontend&lt;br /&gt;
  labels:&lt;br /&gt;
    app: guestbook&lt;br /&gt;
    tier: frontend&lt;br /&gt;
spec:&lt;br /&gt;
  # comment or delete the following line if you want to use a LoadBalancer&lt;br /&gt;
  type: NodePort &lt;br /&gt;
  # if your cluster supports it, uncomment the following to automatically create&lt;br /&gt;
  # an external load-balanced IP for the frontend service.&lt;br /&gt;
  # type: LoadBalancer&lt;br /&gt;
  ports:&lt;br /&gt;
  - port: 80&lt;br /&gt;
  selector:&lt;br /&gt;
    app: guestbook&lt;br /&gt;
    tier: frontend&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
* Apply the Service using {{code|kubectl apply -f frontend-service.yaml}}&lt;br /&gt;
* See Services using {{code|kubectl get services }}&lt;br /&gt;
&lt;br /&gt;
If you use a NodePort and the service looks like this:&lt;br /&gt;
{{highlight|lang=terminal|code=&lt;br /&gt;
[root@kube guestbook]# kubectl get service frontend&lt;br /&gt;
NAME       TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE&lt;br /&gt;
frontend   NodePort   10.97.195.242   &amp;lt;none&amp;gt;        80:32764/TCP   10m&lt;br /&gt;
}}&lt;br /&gt;
You can get to your service by accessing the Node on port 32764.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Namespaces ===&lt;br /&gt;
A namespace organizes objects in the cluster. It is analogous to OU containers in Active Directory, folders in a filesystem, or classes in object oriented languages. By default, new objects are placed in the &#039;default&#039; namespace. Objects cannot see other objects in different namespaces (this applies even to the default namespace). If you have secrets, ensure they match the namespace of the object using the secret for them to be of any use.&lt;br /&gt;
&lt;br /&gt;
=== Contexts ===&lt;br /&gt;
Contexts are like a profile. A context can have different default namespace, or user credentials to manage different clusters.&lt;br /&gt;
&lt;br /&gt;
Change the current context using {{code|kubectl config use-context my-context}}&lt;br /&gt;
&lt;br /&gt;
=== Config File ===&lt;br /&gt;
Located in {{code|~/.kube/config}}. This file contains credentials to authenticate to the cluster.&lt;br /&gt;
&lt;br /&gt;
It contains the default namespace and context values.&lt;br /&gt;
&lt;br /&gt;
=== Kubernetes API ===&lt;br /&gt;
The Kubernetes API is a RESTful API, providing access to the Kubernetes backend.&lt;br /&gt;
&lt;br /&gt;
Objects in the Kubernetes API are represented as JSON or Yaml files. Files can be used to create, update, or delete objects from the server.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Description !! Command&lt;br /&gt;
|-&lt;br /&gt;
| Create/Update || {{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl apply -f obj.yaml&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| Edit || {{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl edit &amp;lt;resource-name&amp;gt; &amp;lt;object-name&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| Delete || {{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl delete -f obj.yaml&lt;br /&gt;
## or&lt;br /&gt;
# kubectl delete &amp;lt;resource-name&amp;gt; &amp;lt;object-name&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
All objects can be annotated or given a label.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Description !! Command&lt;br /&gt;
|-&lt;br /&gt;
| Label pod &#039;bar&#039; {{code|1=color=red}} || {{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl label pods bar color=red&lt;br /&gt;
## pass --overwrite if it already exists.&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| Remove label {{code|color}} from pod &#039;bar&#039; || {{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl label pods bar -color&lt;br /&gt;
}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Master Node ===&lt;br /&gt;
A master node contains containers that provide the API server, scheduler, etc. that manages the cluster.&lt;br /&gt;
&lt;br /&gt;
The master node should have the following components:&lt;br /&gt;
* {{code|controller-manager}}: Responsible for running controllers that regulate behavior int he cluster. Eg. ensure replicas for a service are available and healthy.&lt;br /&gt;
* {{code|scheduler}}: Places pods into different nodes in the cluster&lt;br /&gt;
* {{code|etcd}}: storage for cluster; stores API objects.&lt;br /&gt;
&lt;br /&gt;
All components deployed by Kubernetes run under the kube-system namespace.&lt;br /&gt;
&lt;br /&gt;
{{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl describe nodes kube&lt;br /&gt;
...&lt;br /&gt;
Non-terminated Pods:         (8 in total)&lt;br /&gt;
  Namespace                  Name                            CPU Requests  CPU Limits  Memory Requests  Memory Limits&lt;br /&gt;
  ---------                  ----                            ------------  ----------  ---------------  -------------&lt;br /&gt;
  kube-system                coredns-576cbf47c7-6mphw        100m (2%)     0 (0%)      70Mi (0%)        170Mi (2%)&lt;br /&gt;
  kube-system                coredns-576cbf47c7-75n6g        100m (2%)     0 (0%)      70Mi (0%)        170Mi (2%)&lt;br /&gt;
  kube-system                etcd-kube                       0 (0%)        0 (0%)      0 (0%)           0 (0%)&lt;br /&gt;
  kube-system                kube-apiserver-kube             250m (6%)     0 (0%)      0 (0%)           0 (0%)&lt;br /&gt;
  kube-system                kube-controller-manager-kube    200m (5%)     0 (0%)      0 (0%)           0 (0%)&lt;br /&gt;
  kube-system                kube-proxy-cmdsn                0 (0%)        0 (0%)      0 (0%)           0 (0%)&lt;br /&gt;
  kube-system                kube-scheduler-kube             100m (2%)     0 (0%)      0 (0%)           0 (0%)&lt;br /&gt;
  kube-system                weave-net-swwgs                 20m (0%)      0 (0%)      0 (0%)           0 (0%)&lt;br /&gt;
...&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The Kubernetes proxy is responsible for routing network traffic to services in the kubernetes cluster. (Question: Does it do the load balancing?). A proxy exists on every node.&lt;br /&gt;
&lt;br /&gt;
{{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl get daemonsets --namespace=kube-system&lt;br /&gt;
NAME         DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE&lt;br /&gt;
kube-proxy   1         1         1       1            1           &amp;lt;none&amp;gt;          26h&lt;br /&gt;
weave-net    1         1         1       1            1           &amp;lt;none&amp;gt;          28m&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Question: What is a DaemonSet?&lt;br /&gt;
&lt;br /&gt;
Kubernetes also runs a DNS server that provides naming and discovery for services in the cluster. &lt;br /&gt;
&lt;br /&gt;
{{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl get deployments --namespace=kube-system&lt;br /&gt;
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE&lt;br /&gt;
coredns   2         2         2            2           26h&lt;br /&gt;
&lt;br /&gt;
# kubectl get services --namespace=kube-system&lt;br /&gt;
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE&lt;br /&gt;
kube-dns   ClusterIP   10.96.0.10   &amp;lt;none&amp;gt;        53/UDP,53/TCP   26h&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The DNS service for the cluster runs on 10.96.0.10. If you log into a container in the cluster, this server will be used as the primary DNS server.&lt;br /&gt;
&lt;br /&gt;
Kubernetes Dashboard UI can be installed. Like the DNS service, it is both a deployment and a service:&lt;br /&gt;
{{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl get deployments --namespace=kube-system kubernetes-dashboard&lt;br /&gt;
NAME                   DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE&lt;br /&gt;
kubernetes-dashboard   1         1         1            1           2m26s&lt;br /&gt;
&lt;br /&gt;
[root@kube ~]# kubectl get services --namespace=kube-system kubernetes-dashboard&lt;br /&gt;
NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE&lt;br /&gt;
kubernetes-dashboard   ClusterIP   10.108.158.128   &amp;lt;none&amp;gt;        443/TCP         2m36s&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Run {{code|kubectl proxy}} to proxy the server on {{code|localhost:8001}} and then access it in a web browser at {{code|http://localhost:8001/ui}}. If this is on a remote server, create a SSH tunnel.&lt;br /&gt;
&lt;br /&gt;
=== Kubernetes Node ===&lt;br /&gt;
&lt;br /&gt;
The scheduler will place containers on Kubernetes (worker) nodes. The scheduler does this by checking a node&#039;s taint and will not schedule pods on nodes that contain things like {{code|node-role.kubernetes.io/master:NoSchedule}}. Attempting to do so will result in a {{code|FailedScheduling}} status and a message of {{code|0/1 nodes are available: 1 node(s) had taints that the pod didn&#039;t tolerate.}} when looking at pod events using {{code|kubectl describe pods pod-name}}.&lt;br /&gt;
&lt;br /&gt;
== Commands ==&lt;br /&gt;
&lt;br /&gt;
The {{code|kubectl}} command line tool is the official kubernetes client for interacting with the Kubernetes API.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Description !! Command&lt;br /&gt;
|-&lt;br /&gt;
| Get all nodes&lt;br /&gt;
| {{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl get nodes&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| Get all pods&lt;br /&gt;
| {{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl  get pods  --all-namespaces&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| Get information about a node&lt;br /&gt;
| {{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl describe nodes&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| See components in the cluster&lt;br /&gt;
| {{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl get componentstatuses&lt;br /&gt;
}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Tips:&lt;br /&gt;
When using {{code|kubectl get}}, pass&lt;br /&gt;
* {{code|--no-headers}} to remove headers for easier parsing&lt;br /&gt;
* {{code|-o json{{!}}yaml}} to format output in json/yaml.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Description !! Command&lt;br /&gt;
|-&lt;br /&gt;
| Create a pod&lt;br /&gt;
| {{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl run kuard --image=gcr.io/kuar-demo/kuard-amd64:1&lt;br /&gt;
# kubectl apply -f kuard-pod.yaml&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| Listing pods&lt;br /&gt;
| {{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl get pods&lt;br /&gt;
## Filter by label with -l, can supply multiple of these.&lt;br /&gt;
# kubectl get pods -l label=something&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| Delete pod&lt;br /&gt;
| {{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl delete deployments/kuard&lt;br /&gt;
# kubectl delete -f kuard-pod.yaml&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| Pod Details&lt;br /&gt;
| {{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl describe pods kuard&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| Pod Logs&lt;br /&gt;
| {{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl logs kuard&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| Enter a container&lt;br /&gt;
| {{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl exec kuard cmd&lt;br /&gt;
# kubectl exec -it kuard sh&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| Copy to/from container&lt;br /&gt;
| {{highlight|lang=terminal|code=&lt;br /&gt;
# kubectl cp podname:/src ./dst&lt;br /&gt;
# kubectl cp ./src podname:/dst&lt;br /&gt;
}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A pod manifest looks something like this:&lt;br /&gt;
{{highlight|lang=text|code=&lt;br /&gt;
apiVersion: v1&lt;br /&gt;
kind: Pod&lt;br /&gt;
metadata:&lt;br /&gt;
  name: kuard&lt;br /&gt;
spec:&lt;br /&gt;
  containers:&lt;br /&gt;
    - image: gcr.io/kuar-demo/kuard-amd64:1&lt;br /&gt;
      name: kuard&lt;br /&gt;
      ports:&lt;br /&gt;
        - containerPort: 8080&lt;br /&gt;
          name: http&lt;br /&gt;
          protocol: TCP&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Questions ==&lt;br /&gt;
* What is involved in setting up a cluster on multiple VMs?&lt;br /&gt;
* What is the Kubernetes API?&lt;br /&gt;
* What is this persistent storage (etcd)?&lt;br /&gt;
* What is the WeaveWorks network and how does it work?&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [https://kubernetes.io/docs/reference/kubectl/cheatsheet/ Command cheat sheet]&lt;br /&gt;
* Kubernetes: Up &amp;amp; Running&lt;br /&gt;
* CouchDB failover demo: https://blog.couchbase.com/databases-on-kubernetes/&lt;br /&gt;
* [https://medium.freecodecamp.org/learn-kubernetes-in-under-3-hours-a-detailed-guide-to-orchestrating-containers-114ff420e882?gi=f98022e78170 A Kubernetes Guide]&lt;br /&gt;
* https://kubernetes.io/docs/tutorials/stateless-application/guestbook/ Simple overview on deploying a guestbook application &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;s&amp;gt;MySQL on Kubernetes https://www.youtube.com/watch?v=J7h0F34iBx0&amp;lt;/s&amp;gt; Not exactly beginner friendly. Goes over the MySQLOperator and Vitess&lt;/div&gt;</summary>
		<author><name>136.159.160.201</name></author>
	</entry>
</feed>