StatefulSet


Purpose

1. creation order is guaranteed unless podManagementPolicy: parallel. The default podManagementPolicy value is OrderedReady
2. pod name remain same even after restart
3. Use volumeClaimTemplate . Its an array. The content of array element is same as PVC. Each pod will get its own PV.

If we delete statefulset then all pods may not get deleted. First we shall scale statefulset to 0 then delete statefulset. After that we shall manually delete PVC.

For statefulset hostname and pod name are same. 

kubectl patch statefulset
It can be used to update: 
- label
- annotation
- container image
- resource requests
- resource limits

Two types of updtateStrategy
- RollingUpdate: The RollingUpdate update strategy will update all Pods in a StatefulSet, in reverse ordinal order
- OnDelete
During update, if any pod, that is not under update process, fails, then it will restored back to its original version. Support N pod. Updates goes from pod-N to pod-1 and change container image to version 1 to version 2. Now suppose update for pod-i is going on. pod-j is crashed. if j > i then it will be restored back to version 2 and if j < i then it will be restored back to version 1

Headeless service will add DNS entries
- for each pod: "pod name"."headless service name"."namespace name".svc.cluster.local
Here pod IP address is not used.
- for headeless service: DNS is mapped to all pod's DNS. 

To create Headless service, specify ClusterIP: None

1. Headless service with deployment. 
Pod shall have value for subdomain as same as name of headless service.
Also specify hostname then only pod's dns name A record will be created. But all pod will have same hostname. 

2. To create Headless service with statefulset, no need to specify (1) subdomain (2) hostname

Instead of subdomain, we shall specify serviceName

CKAD : 8.Troubleshooting


Tools
* busybox container has shell
* DNS configuration file
* dig (for DNS lookup)
* tcpdump
* Prometheus
* Fluentd

Commands
k exec -ti "deployment name"+Tab -- /bin/sh

Logging
Log Command
k logs "pod name"
- this command can also be used to find out name of containers, if there are multiple container inside pod.
To get live stream of logs use -f option. Same as we add -f to tail : tail -f
The actual command is: 
k logs "pod name" "container name"
k logs "pod name" --all-containers=true
k logs command has some useful options like
--tail="N"
--since="1h"
-l for selector
--max-log-results="N" along with -l
-p for previous instance 
--time-stamps=true to add timestamp on each line. 
- Without logs, we can deploy sidecar container that generates logs. (1) stream application logs to their own stdout OR (2) run a logging agent. 
The Kubelet uses Docker logging driver to write container logs to local files. These logs are retrieved by k logs command. 
Tools
Elastic Search, Logstash, Kibana Stack (ELK), Fluentd
Fluent agent is daemonset. It feeds data to Elastic Search. Then one can visualize at Kibana dashboard. 

kubelet is a non-container component. its log found in "/var/log/journal" folder. It is access with command journalctl -a


Networking
- DNS, firewall, general connectivity, using standard linux command tools
Changes at switches, routes, or other network settings. Inter node networking. Look at all recent relevant / irrelevant infrastructure changes. 

Security
- RBAC,
- SELinux and AppArmor are important to check, for network-centric applications. 
Disable security and test again
Refer log of tools, for find out rule violation.
Fix possible multiple issues and then re-enable security


Other Points
- check node logs for errors. Make sure enough resources are allocated
- pod logs and state of pod
- troubleshoot pod DNS and pod network
- API calls between (1) controller < - > (2) kube API server
- inter node network issue: DNS, firewall

K8s Troubleshooting is similar to data center troubleshooting. Main differences are:
- See pod state: pending and error state
- See error in log files
- check resources are enough

Prometheus
counter, gauge, Histogram (server side), Summary (client side)

MetricsServer
It has only in memory DB. Now heapster is deprecated. 
With MetricsServer we can use command
k top node
k top pod

Jaeger
feature: 
- distributed context propagation
- transaction monitoring
- root cause analysis

Conformance Testing
Tool: 
1. Sonobuoy https://sonobuoy.io/ , https://github.com/vmware-tanzu/sonobuoy
2. https://github.com/cncf/k8s-conformance/blob/master/instructions.md
3. Heptio

It makes sure that
- workload on one distribution works on another. 
- API functions the same
- Minimum functionality exists. 

Misc

Inside pod, each container has its own restart count. We can check by running command k describe pod . Pod's restart count is summation of restart count of all containers. 

nslookup FQDN command is to check DNS query gets resolved or not. its configuration is /etc/resolv.conf (not resolve)

If pod is within service then it can have its DNS name as 
"hyphen separated IP address"."pod name"."service name"."namespace name".svc.cluster.local

If pod is part of deployment, then pod name is not the absolute name. 
If we change label of any pod in deployment, with --overwrite option then it will be removed from service, a new pod will be created. The removed pod's DNS entry will also get removed and new pod's DNS entry will be added. 

To add label key=value on k8s object (e.g. pod) command is:
k label 'object type' 'object name' key=value

To overwrite label key=value1 
k label 'object type' 'object name' --overwrite key=value1

To remove label with key
k label 'object type' 'object name' key-

There is no DNS entry for naked pod. There is no entry for pod, that belongs to daemon set. 

With wget command, we can check DNS resolution is working or not. 

Kube-proxy

We can check kube-proxy log by
k -n kube-system

8.1: 11,13


Reference: 

https://kubernetes.io/docs/concepts/cluster-administration/logging/
https://kubernetes.io/docs/tasks/debug-application-cluster/logging-elasticsearch-kibana/

https://kubernetes.io/docs/tasks/debug-application-cluster/troubleshooting/
https://kubernetes.io/docs/tasks/debug-application-cluster/debug-application/
https://kubernetes.io/docs/tasks/debug-application-cluster/debug-cluster/
https://kubernetes.io/docs/tasks/debug-application-cluster/debug-pod-replication-controller/
https://kubernetes.io/docs/tasks/debug-application-cluster/debug-service/
https://github.com/kubernetes/kubernetes/issues

CKAD
https://github.com/dgkanatsios/CKAD-exercises
https://github.com/lucassha/CKAD-resources

CKAD : 7.Exposing Applications


ClusterIP range is defined via API server startup option --service-cluster-ip-range
NodePort range is defined in cluster configuration. 
ExternalName has no port, no selector, no endpoint. Redirection happen at DNS level. 
'kubectl proxy' command create a local service, to access ClusterIP. Useful for troubleshooting and development work. 

If we create service with LoadBalancer type on bare metal, and we have not deployed any load balancer then also we can access it as NodePort service. 

Grace Period

We should add 

--grace-period=0 --force
for immediate deletion

pod and deployment have terminationGracePeriodSeconds parameter in spec section. One cannot modify it runtime with kubectl edit command. We can modify it during deployment time only. 

KubeProxy Mode
* K8s 1.0 userpace mode
* K8s 1.1 iptables introduced
1.2 iptables become default
it allows max upto approx 5000 worker nodes. 
* K8s 1.9 ipvs. configurable load balancing algorithms
- round-robin
- shortest expected delay
- least connection
- others. 
IPVS kernel module shall be installed and running. 

KubeProxy Mode is configured as startup flag
mode=iptables, mode=IPVS, mode=userspace

Accessing an application with a service
k expose deploy "deploy name" --port=80 --type=NodePort

We can expose pod also as service, if pod has label
k expose pod "pod name" --port=80 --type=NodePort

The targetPort value by default set as value of port. 
port is part of endpoint: clusterIP:port
targetPort is opened at pod. 

Service can point to service in different namespace, to service which is outside cluster. 

External Name is used to access resource, external to cluster. Here selector is not used. 

Ingress resource
match : host and path both
rules: HTTP rules only to direct traffic. 

Usecase:
- Fan out to service
- name based hosting
- TLS
- load balancing
- expose low numbered port

Ingress Controller
Officially supported 
- nginx
- GCE
Community supported
- Traefik (pronounced Traffic) 
- HAProxy 
Other: 
- Contour
- Istio


Ingress controller can be deployed as daemonset. It has its own service account, ClusterRole and ClusterRoleBinding. ClusterRole includes (1) get (2) list (3) watch access to (1) service (2) ep (3) secrets and (4) ingress resource. 

Ingress resource has rules. This rule is kind of similar to (1) Ingress GW (2) Virtual Service (3) Destination Rule in Istio. 

Ingress resource is created in a same namespace where we have all the svc and deployment. 

Traefik has nice UI also accessible with default 8080 port

Questions
What is difference between containerPort and targetPort ? 






Prometheus


1. Run this script

KUBEADM_SYSTEMD_CONF=/etc/systemd/system/kubelet.service.d/10-kubeadm.conf
sed -e "/cadvisor-port=0/d" -i "$KUBEADM_SYSTEMD_CONF"
if ! grep -q "authentication-token-webhook=true" "$KUBEADM_SYSTEMD_CONF"; then
  sed -e "s/--authorization-mode=Webhook/--authentication-token-webhook=true --authorization-mode=Webhook/" -i "$KUBEADM_SYSTEMD_CONF"
fi
systemctl daemon-reload
systemctl restart kubelet

If needed step 2 to 6
2. change "--bind-address" value from 127.0.0.1 to 0.0.0.0 in below two files

/etc/kubernetes/manifests/kube-controller-manager.yaml
/etc/kubernetes/manifests/kube-scheduler.yaml

3. Run below two commands (optional) 

k delete pod kube-controller-manager-minikube -n kube-system
k delete pod kube-scheduler-minikube -n kube-system

4. run command
kubectl api-resources | grep deployment

5. run command
kubectl api-resources | grep DaemonSet
Do require changes

6. kubectl edit clusterrole system:node

add following section in - apiGroups:

- apiGroups:
  - ""
  resources:
  - nodes/proxy
  verbs:
  - get

if needed step 7
7 k edit clusterrole prometheus

add "nodes/metrics"

URLs

http://127.0.0.1:30990/ Prometheus 
http://127.0.0.1:31400/  Grafana
http://127.0.0.1:30993/ Prometheus Alert Manager
=========================

The Prometheus resource declaratively describes the desired state of a Prometheus deployment, while a ServiceMonitor describes the set of targets to be monitored by Prometheus.

Reference : 
https://github.com/coreos/prometheus-operator/blob/master/Documentation/user-guides/getting-started.md

The Prometheus Operator reconciles services called prometheus-operated and alertmanager-operated, which are used as governing Services for the StatefulSets. To perform this reconciliation

The custom resources that the Prometheus Operator introduces are:
  • Prometheus
  • ServiceMonitor
  • PodMonitor
  • Alertmanager
  • PrometheusRule

CKAD : 6.Security


Authentication
- X.509 client cert
- static token
- bearer or bootstrap token
- static password file
- service account
- OpenID connect tokens

Kube API server options
- basic-auth-file
- oidc-issuer-url
- token-auth-file
- authorization-webhook-config-file

Authorization
Kube API server option -authorization-mode
Values
- ABAC (API server additional option: - authorization-policy-file="file_name.json")
- RBAC
- Webhook
- AlwaysAllow
- AlwaysDeny

Authorization policy has user, group, namespace, verb (=operation) 

Role = Many rules
Rule = 
+ apiGroups
+ resources
+ resourceName
+ verb (= operation) 

RoleBinding maps (1) role and 
2.1 Service Account OR
2.2 User Account (mapped with context) OR
2.3 Group

The service account can be associated with pod or with deployment using serviceAccountName
It mounts a secret with name "service account name - token - random" at path 
/var/run/secrets/kubernetes.io/serviceaccount path. This path has 3 files.
1. ca.cert
2. namespace
3. token

All files stored secrets in plain text format
The values are stored at etcd in base64 encoded format
we can very with command
base64 -d "file name"
echo "plain text" | base64

securityContext

Mapped with pod or containers inside pod. E.g.
- UID of process
- Linux capabilities (for containers) 
- filesystem group
securityContext is cluster level rules 

It can present at container level or pod level or both level. 
If both are defined then securityContext at container level will override securityContext of container level. 
If we have pod level securityContext about runAsUser then nginx container is not able to start. This container want to create a path /var/cache/nginx/client_temp it is possible with runAsUser 1 by default. 

PodSecurityPolicieis (PSP) automate enforcement of securityContext. 

To enable PSP, configure admission-controller of the controller manager to have PSP. 

Network Policies 
supported by CNI plugins: Calico, Romana, Cilium, Kube-router, WeaveNet 
With network policy, all pod can communicate with all pods. So with network policy, let forbid communication from all pod to all pod and the allow as per requirement
- based on namespaceSelector
- based on podSelector (matchLabels) 
- to IP address + port
- from IP address + port

The policyTypes are Ingress and Egress. 

For WeveNet CNI plugin, we shall add annotation of network policy name at namespace. The flannel CNI plugin does not honor network policy

The Calico CNI shall be installed. Download latest calico.yaml file. Then install by command

k create -f calico.yaml

While starting minikube pass this additional flag

--extra-config=kubelet.network-plugin=cni --network-pugin=cni

We can add whitelist as below. 

ingress:
- from:
  - ipBlock:
      cidr: 192.168.0.0/16
  ports:
  - port: 80
    protocol: TCP



Allow all ingress traffic

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-ingress
spec:
  podSelector: {}
  ingress:
  - {}
  policyTypes:

  - Ingress

Allow all egress traffic

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-egress
spec:
  podSelector: {}
  egress:
  - {}
  policyTypes:

  - Egress

Deny all ingress traffic 

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
spec:
  podSelector: {}
  policyTypes:

  - Ingress

Deny all egress traffic

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
spec:
  podSelector: {}
  policyTypes:

  - Egress

All policies are add / union. So there is no chance of conflict. 
Whitelist can be keep growing. 

Capabilities:

We can run this command inside container

grep Cap /proc/1/status

CapInh: 00000000a80425fb 
CapPrm: 0000000000000000 
CapEff: 0000000000000000 
CapBnd: 00000000a80425fb 
CapAmb: 0000000000000000

The capability can be decoded with

capsh --decode=00000000a80425fb

Capability can be added under securityContext

capabilities: 
  add: ["NET_ADMIN", "SYS_TIME", "MAC_ADMIN"]

References: 
https://github.com/kelseyhightower/kubernetes-the-hard-way
https://kubernetes.io/docs/reference/access-authn-authz/controlling-access/
https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/
https://kubernetes.io/docs/reference/access-authn-authz/abac/#examples
https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
https://github.com/kubernetes/examples/blob/master/staging/podsecuritypolicy/rbac/README.md
https://github.com/ahmetb/kubernetes-network-policy-recipes
https://kubernetes.io/docs/concepts/services-networking/network-policies/