↓ Skip to main content
Kubernetes

K8S: Deployment

Table of Contents

Time to re-test how to create deployments. It has been sometime, I created some deployments so just checking on how much I remember.

The quick way to always get started is to check the HELP.

Cartoon figure looking through a large magnifying glass

k create --help
#

Create a resource from a file or from stdin. 

JSON and YAML formats are accepted.

Examples:
  # Create a pod using the data in pod.json.
  kubectl create -f ./pod.json
  
  # Create a pod based on the JSON passed into stdin.
  cat pod.json | kubectl create -f -
  
  # Edit the data in docker-registry.yaml in JSON then create the resource using the edited data.
  kubectl create -f docker-registry.yaml --edit -o json

Available Commands:
  clusterrole         Create a ClusterRole.
  clusterrolebinding  Create a ClusterRoleBinding for a particular ClusterRole
  configmap           Create a configmap from a local file, directory or literal value
  deployment          Create a deployment with the specified name.
  job                 Create a job with the specified name.
  namespace           Create a namespace with the specified name
  poddisruptionbudget Create a pod disruption budget with the specified name.
  priorityclass       Create a priorityclass with the specified name.
  quota               Create a quota with the specified name.
  role                Create a role with single rule.
  rolebinding         Create a RoleBinding for a particular Role or ClusterRole
  secret              Create a secret using specified subcommand
  service             Create a service using specified subcommand.
  serviceaccount      Create a service account with the specified name

Options:
      --allow-missing-template-keys=true: If true, ignore any errors in templates when a field or map key is missing in
the template. Only applies to golang and jsonpath output formats.
      --dry-run=false: If true, only print the object that would be sent, without sending it.
      --edit=false: Edit the API resource before creating
  -f, --filename=[]: Filename, directory, or URL to files to use to create the resource
  -o, --output='': Output format. One of:
json|yaml|name|template|go-template|go-template-file|templatefile|jsonpath|jsonpath-file.
      --raw='': Raw URI to POST to the server.  Uses the transport specified by the kubeconfig file.
      --record=false: Record current kubectl command in the resource annotation. If set to false, do not record the
command. If set to true, record the command. If not set, default to updating the existing annotation value only if one
already exists.
  -R, --recursive=false: Process the directory used in -f, --filename recursively. Useful when you want to manage
related manifests organized within the same directory.
      --save-config=false: If true, the configuration of current object will be saved in its annotation. Otherwise, the
annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.
  -l, --selector='': Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)
      --template='': Template string or path to template file to use when -o=go-template, -o=go-template-file. The
template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
      --validate=true: If true, use a schema to validate the input before sending it
      --windows-line-endings=false: Only relevant if --edit=true. Defaults to the line ending native to your platform.

Usage:
  kubectl create -f FILENAME [options]

Use "kubectl <command> --help" for more information about a given command.
Use "kubectl options" for a list of global command-line options (applies to all commands).
k create deployment <my-deployment> --image=<Image-Name> --dry-run=true --allow-missing-template-keys=true -o=yaml

The output has been set to YAML to see what it will output and I can use that to create my own deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: store-deployment
  name: store-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: store-deployment
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: store-deployment
    spec:
      containers:
      - image: <Image-Name>:1.0.0
        name: store-products
        resources: {}
status: {}

Once deployment is done Time to create a service

k create service clusterip store-products --tcp=80:80 -o=json
{
    "apiVersion": "v1",
    "kind": "Service",
    "metadata": {
        "creationTimestamp": "2020-12-22T12:36:19Z",
        "labels": {
            "app": "store-products"
        },
        "name": "store-products",
        "namespace": "default",
        "resourceVersion": "7436",
        "selfLink": "/api/v1/namespaces/default/services/store-products",
        "uid": "4adac30d-4452-11eb-b86b-1276d3e8b6fb"
    },
    "spec": {
        "clusterIP": "10.97.209.47",
        "ports": [
            {
                "name": "80-80",
                "port": 80,
                "protocol": "TCP",
                "targetPort": 80
            }
        ],
        "selector": {
            "app": "store-products"
        },
        "sessionAffinity": "None",
        "type": "ClusterIP"
    },
    "status": {
        "loadBalancer": {}
    }
}
k exec busybox -- curl -s store-products
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: 2020-12-22T12:36:19Z
  labels:
    app: store-products
  name: store-products
  namespace: default
  resourceVersion: "7436"
  selfLink: /api/v1/namespaces/default/services/store-products
  uid: 4adac30d-4452-11eb-b86b-1276d3e8b6fb
spec:
  clusterIP: 10.97.209.47
  ports:
  - name: 80-80
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: store-products
  sessionAffinity: None
  type: ClusterIP
status:
  loadBalancer: {}
~

Namespace
#

It is always a good practice to create components under a specific namespace to avoid name collisions

k create ns my-shop --dry-run 
namespace/my-shop created (dry run)
k create ns my-shop
namespace/my-shop created
k get ns
NAME          STATUS   AGE
default       Active   152m
kube-public   Active   152m
kube-system   Active   152m
my-shop       Active   2s
Author
Samarthya
Engineer, learner, tinkerer. This is my trophy shelf of everyday work and leisure.

Related

Services: K8S

·3 mins
There are multiple Kubernetes objects we will be talking about in this blog. Mainly Services, Selectors and Labels. Service is an abstraction which defines a logical set of Pods and a policy by which to access them. A Service in Kubernetes is a REST object, similar to a Pod. Service tags the pods, logically grouping them using selectors. Pods have a lifecycle, they are born, they live, process and then they die. The pods (desired state) can be managed using deployment. A label is an identifying attribute of an object, and can be defined at the creation time, and subsequently modified and added at any time. Label selector is a grouping primitive in Kubernetes and allows client/user to identify a set of objects. There are two sets of selectors equality-based and set-based. An abstract way to expose an application running on a set of Pods as a network service. The set of Pods targeted by a Service is usually determined by a selector.

Installing K8S on Ubuntu

·5 mins
Install docker cat /etc/issue Ubuntu 18.04.4 LTS \n \l sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable" sudo apt-get update sudo apt-get install -y docker-ce=18.06.1~ce~3-0~ubuntu sudo apt-mark hold docker-ce apt-mark --help apt 1.6.12ubuntu0.2 (amd64) Usage: apt-mark [options] {auto|manual} pkg1 [pkg2 ...] apt-mark is a simple command line interface for marking packages as manually or automatically installed. It can also be used to manipulate the dpkg(1) selection states of packages, and to list all packages with or without a certain marking. lsb_release -c Codename: bionic lsb_release -cs bionic systemctl status docker ● docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2020-12-14 09:05:39 UTC; 45s ago Docs: https://docs.docker.com Main PID: 662 (dockerd) Tasks: 21 CGroup: /system.slice/docker.service ├─662 /usr/bin/dockerd -H fd:// └─685 docker-containerd --config /var/run/docker/containerd/containerd.toml Dec 14 09:05:39 ip-10-0-1-101 dockerd[662]: time="2020-12-14T09:05:39.297237656Z" level=info msg="ClientConn switching balancer to \"pick_first\"" module=grpc Dec 14 09:05:39 ip-10-0-1-101 dockerd[662]: time="2020-12-14T09:05:39.297281586Z" level=info msg="pickfirstBalancer: HandleSubConnStateChange: 0xc4201b7df0, CONNECTING" module=grpc Dec 14 09:05:39 ip-10-0-1-101 dockerd[662]: time="2020-12-14T09:05:39.297797167Z" level=info msg="pickfirstBalancer: HandleSubConnStateChange: 0xc4201b7df0, READY" module=grpc Dec 14 09:05:39 ip-10-0-1-101 dockerd[662]: time="2020-12-14T09:05:39.297852837Z" level=info msg="Loading containers: start." Dec 14 09:05:39 ip-10-0-1-101 dockerd[662]: time="2020-12-14T09:05:39.596242360Z" level=info msg="Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to set a preferred IP addres Dec 14 09:05:39 ip-10-0-1-101 dockerd[662]: time="2020-12-14T09:05:39.753685539Z" level=info msg="Loading containers: done." Dec 14 09:05:39 ip-10-0-1-101 dockerd[662]: time="2020-12-14T09:05:39.822291121Z" level=info msg="Docker daemon" commit=e68fc7a graphdriver(s)=overlay2 version=18.06.1-ce Dec 14 09:05:39 ip-10-0-1-101 dockerd[662]: time="2020-12-14T09:05:39.822430053Z" level=info msg="Daemon has completed initialization" Dec 14 09:05:39 ip-10-0-1-101 dockerd[662]: time="2020-12-14T09:05:39.853660664Z" level=info msg="API listen on /var/run/docker.sock" Dec 14 09:05:39 ip-10-0-1-101 systemd[1]: Started Docker Application Container Engine. curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - cat << EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list deb https://apt.kubernetes.io/ kubernetes-xenial main EOF sudo apt-get update sudo apt-get install -y kubelet=1.14.5-00 kubeadm=1.14.5-00 kubectl=1.14.5-00 sudo apt-mark hold kubelet kubeadm kubectl sudo kubeadm init --pod-network-cidr=10.244.0.0/16 I1214 09:10:37.236647 3055 version.go:240] remote version is much newer: v1.20.0; falling back to: stable-1.14 [init] Using Kubernetes version: v1.14.10 [preflight] Running pre-flight checks [WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/ [preflight] Pulling images required for setting up a Kubernetes cluster [preflight] This might take a minute or two, depending on the speed of your internet connection [preflight] You can also perform this action in beforehand using 'kubeadm config images pull' [kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env" [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml" [kubelet-start] Activating the kubelet service [certs] Using certificateDir folder "/etc/kubernetes/pki" [certs] Generating "etcd/ca" certificate and key [certs] Generating "etcd/server" certificate and key [certs] etcd/server serving cert is signed for DNS names [ip-10-0-1-101 localhost] and IPs [10.0.1.101 127.0.0.1 ::1] [certs] Generating "etcd/peer" certificate and key [certs] etcd/peer serving cert is signed for DNS names [ip-10-0-1-101 localhost] and IPs [10.0.1.101 127.0.0.1 ::1] [certs] Generating "apiserver-etcd-client" certificate and key [certs] Generating "etcd/healthcheck-client" certificate and key [certs] Generating "ca" certificate and key [certs] Generating "apiserver-kubelet-client" certificate and key [certs] Generating "apiserver" certificate and key [certs] apiserver serving cert is signed for DNS names [ip-10-0-1-101 kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 10.0.1.101] [certs] Generating "front-proxy-ca" certificate and key [certs] Generating "front-proxy-client" certificate and key [certs] Generating "sa" key and public key [kubeconfig] Using kubeconfig folder "/etc/kubernetes" [kubeconfig] Writing "admin.conf" kubeconfig file [kubeconfig] Writing "kubelet.conf" kubeconfig file [kubeconfig] Writing "controller-manager.conf" kubeconfig file [kubeconfig] Writing "scheduler.conf" kubeconfig file [control-plane] Using manifest folder "/etc/kubernetes/manifests" [control-plane] Creating static Pod manifest for "kube-apiserver" [control-plane] Creating static Pod manifest for "kube-controller-manager" [control-plane] Creating static Pod manifest for "kube-scheduler" [etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests" [wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s [apiclient] All control plane components are healthy after 16.001809 seconds [upload-config] storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace [kubelet] Creating a ConfigMap "kubelet-config-1.14" in namespace kube-system with the configuration for the kubelets in the cluster [upload-certs] Skipping phase. Please see --experimental-upload-certs [mark-control-plane] Marking the node ip-10-0-1-101 as control-plane by adding the label "node-role.kubernetes.io/master=''" [mark-control-plane] Marking the node ip-10-0-1-101 as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule] [bootstrap-token] Using token: xtpkvj.e81gaeg0v18shctg [bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles [bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials [bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token [bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster [bootstrap-token] creating the "cluster-info" ConfigMap in the "kube-public" namespace [addons] Applied essential addon: CoreDNS [addons] Applied essential addon: kube-proxy Your Kubernetes control-plane has initialized successfully! To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config You should now deploy a pod network to the cluster. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-administration/addons/ Then you can join any number of worker nodes by running the following on each as root: kubeadm join 10.0.1.101:6443 --token xtpkvj.e81gaeg0v18shctg \ --discovery-token-ca-cert-hash sha256:6c79fda4db86da060f083b35def6c39790c47f6533ab8f7ebb6ea30c2c2af6a3

Metric Server

·4 mins
For my local K8S cluster of 4 nodes I wanted to get the resource usage metrics. From the official documentation of kubernetes.io These metrics can be accessed either directly by the user with the kubectl top command, or by a controller in the cluster, for example Horizontal Pod Autoscaler, to make decisions. https://kubernetes.io