Redis Sentinel VS Cluster

Redis Sentinel runs as a separate program. You should have atleast 3 Sentinel instances monitoring a master instance and its slaves. Sentinel instances try to find consensus when doing a failover and only an odd number of instances will prevent most problems, 3 being the minimum. In this case one of the Sentinel instances can go down and a failover will still work as (hopefully) the other two instances reach consensus which slave to promote.

Redis Cluster is a data sharding solution with automatic managementhandling failover and replication.

K8s – SecurityContext -Notes /Openshift SCC

apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  volumes:
  - name: sec-ctx-vol
    emptyDir: {}
  containers:
  - name: sec-ctx-demo
    image: busybox:1.28
    command: [ "sh", "-c", "sleep 1h" ]
    volumeMounts:
    - name: sec-ctx-vol
      mountPath: /data/demo
    securityContext:
      allowPrivilegeEscalation: false

securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000

In the configuration file, the runAsUser field specifies that for any Containers in the Pod, all processes run with user ID 1000. The runAsGroup field specifies the primary group ID of 3000 for all processes within any containers of the Pod. If this field is omitted, the primary group ID of the containers will be root(0). Any files created will also be owned by user 1000 and group 3000 when runAsGroup is specified. Since fsGroup field is specified, all processes of the container are also part of the supplementary group ID 2000. The owner for volume /data/demo and any files created in that volume will be Group ID 2000.

Openshift UID: https://cloud.redhat.com/blog/a-guide-to-openshift-and-uids

UID Explanations:

https://developer.ibm.com/learningpaths/secure-context-constraints-openshift/deployment-specify-permissions/

https://cloud.redhat.com/blog/a-guide-to-openshift-and-uids

https://andreaskaris.github.io/blog/openshift/scc/

https://www.redhat.com/sysadmin/security-context-constraint-configuration

oc get project projectname -o yaml -it will output the

During the creation of a project or namespace, OpenShift assigns a User ID (UID) range, a supplemental group ID (GID) range, and unique SELinux MCS labels to the project or namespace. By default, no range is explicitly defined for fsGroup, instead, by default, fsGroup is equal to the minimum value of the “openshift.io/sa.scc.supplemental-groups” annotation

The range of UIDs, GIDs, and SELinux MCS labels are unique to the project and there will not be overlap with the UIDs or GIDs assigned to other projects. 

When a Pod is deployed into the namespace, by default, OpenShift will use the first UID and first GID from this range to run the Pod. Any attempt by a Pod definition to specify a UID outside the assigned range will fail and requires special privileges.

SELinu: Security Enhanced Linux

# Creating ServiceAccount with “anyuid” SCC
$ oc create sa sa-with-anyuid
$ oc adm policy add-scc-to-user anyuid -z sa-with-anyuid

Service account is like the user,. and scc is like the role (anyuid is the scc)

oc get scc| grep anyuid

oc describe scc anyuid

7 scc are added to the cluster by default, and only cluster admin could see it.

In OpenShift the Security Context Constraints (SCC) are used to manage and control the permissions and capabilities granted to a Pod. There are eight (8) SCC pre-defined in an OpenShift 4.4 cluster and, by default, each namespace is created with three (3) ServiceAccounts.

oc get scc

oc get -o yaml –export scc/privileged

Lessons learned: we can apply multiple SCCs to a ServiceAccount. The default SCC is always restricted. The matching goes by priority first, then most restrictive policy, then by name. And if a policy does not match a specific request, another one might “jump in” and “help out”.

https://andreaskaris.github.io/blog/openshift/scc/ –the prority

Highest priority first, nil is considered a 0 priority

If priorities are equal, the SCCs will be sorted from most restrictive to least restrictive

If both priorities and restrictions are equal the SCCs will be sorted by name

K8s(Volumes/PVC/PV)

AWS EBS create the storageClass

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/aws-ebs
parameters:
  type: io1
  iopsPerGB: "10"
  fsType: ext4

https://kubernetes.io/docs/concepts/storage/storage-classes/    
provisioner :  ebs , azure files systems

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: example-nfs
provisioner: example.com/external-nfs
parameters:
  server: nfs-server.example.com
  path: /share
  readOnly: "false"

Create dynamic provision PVC :

Users request dynamically provisioned storage by including a storage class in their PersistentVolumeClaim

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: claim1
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: fast
  resources:
    requests:
      storage: 30Gi

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 8Gi
  storageClassName: slow
  selector:
    matchLabels:
      release: "stable"
    matchExpressions:
      - {key: environment, operator: In, values: [dev]}
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: myfrontend
      image: nginx
      volumeMounts:
      - mountPath: "/var/www/html"
        name: mypd
  volumes:
    - name: mypd
      persistentVolumeClaim:
        claimName: myclaim

PVs are resources in the cluster. PVCs are requests for those resources and also act as claim checks to the resource

PV & PVC: https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/#create-a-persistentvolume

Create PV:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: task-pv-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"

Create PVC:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: task-pv-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi

After you create the PersistentVolumeClaim, the Kubernetes control plane looks for a PersistentVolume that satisfies the claim’s requirements. If the control plane finds a suitable PersistentVolume with the same StorageClass, it binds the claim to the volume.

Create NFS no need to create the storage class….

apiVersion: v1

kind: PersistentVolume

metadata:

  name: <nfs pv name>

spec:

  capacity:

    storage:10g

  accessModes:

  – ReadWriteOnce

  nfs:

    path: <nfs share path>

    server: <nfs server ip or hostname>

so are the openshift(pv 7 pvc :

https://infohub.delltechnologies.com/l/deployment-guide-red-hat-openshift-container-platform-4-2/creating-a-pvc-using-nfs-5)

A PV can have a class, which is specified by setting the storageClassName attribute to the name of a StorageClass. A PV of a particular class can only be bound to PVCs requesting that class. A PV with no storageClassName has no class and can only be bound to PVCs that request no particular class.

When a PVC specifies a selector in addition to requesting a StorageClass, the requirements are ANDed together: only a PV of the requested class and with the requested labels may be bound to the PVC.

Claim as volumes

LimitRange/Volumes

apiVersion: v1
kind: LimitRange
metadata:
  name: mem-min-max-demo-lr
spec:
  limits:
  - max:
      memory: 1Gi
    min:
      memory: 500Mi
    type: Container
apiVersion: v1
kind: LimitRange
metadata:
  name: cpu-min-max-demo-lr
spec:
  limits:
  - max:
      cpu: "800m"
    min:
      cpu: "200m"
    type: Container

The Container is running in a namespace that has a default memory limit, and the Container is automatically assigned the default limit. Cluster administrators can use a LimitRange to specify a default value for the memory limit.

Volume

1.emptyDir : this Pod has a Volume of type emptyDir that lasts for the life of the Pod, even if the Container terminates and restarts. Here is the configuration file for the Pod:

Note: A container crashing does not remove a Pod from a node. The data in an emptyDir volume is safe across container crashes.

oc get limitrange rangeName -o yaml

with the limitRange: when create the container without request, it will apply with the LimitRange

https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/cpu-default-namespace/

K8s -DNS- Headless Service-Access Services

DNS Records -https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/

What objects get DNS records?

  1. Services
  2. Pods

Services:

“Normal” (not headless) Services are assigned DNS A and/or AAAA records, depending on the IP family or families of the Service, with a name of the form my-svc.my-namespace.svc.cluster-domain.example. This resolves to the cluster IP of the Service.

Headless Services (without a cluster IP) Services are also assigned DNS A and/or AAAA records, with a name of the form my-svc.my-namespace.svc.cluster-domain.example. Unlike normal Services, this resolves to the set of IPs of all of the Pods selected by the Service. Clients are expected to consume the set or else use standard round-robin selection from the set

Access Services Running on Cluster: https://kubernetes.io/docs/tasks/access-application-cluster/access-cluster-services/

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app.kubernetes.io/name: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

This specification creates a new Service object named “my-service”, which targets TCP port 9376 on any Pod with the app.kubernetes.io/name=MyApp label.

without selector, the endpointsslice of the services will nto be created auto, so have to create endpointslice – refer: https://kubernetes.io/docs/concepts/services-networking/service/

kubectl expose deployment source-ip-app –name=clusterip –port=80 –target-port=8080

kubectl expose deployment source-ip-app –name=nodeport –port=80 –target-port=8080 –type=NodePort

NodePort vs LoadBalancer:

View at Medium.com

https://stackoverflow.com/questions/41509439/whats-the-difference-between-clusterip-nodeport-and-loadbalancer-service-types

k8s- command

https://kubernetes.io/docs/tasks/manage-kubernetes-objects/imperative-command/

playground:https://killercoda.com/

kubectl create service clusterip my-svc –clusterip=”None” -o yaml –dry-run=client > srv.yaml –

kubectl create -f serv.yaml

kubectl delete -f serv.yaml

kubectl get -f <filename|url> -o yaml

kubectl get -h (get the help options for all options)

kubectl get -f <filename|url> -o yaml > test_delete.yaml

kubctl delete -f test_delete.yaml

kubectl apply -f applytest.yaml

kubectl create -f test.yaml

kubectl get test.yaml -o yaml

The last-applied-configuration annotation has been updated with the new image.

To-be-reviewed

How to use kustomize command: https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/

kubectl kustomize <kustomization_directory>

eg:

echo -n 'admin' > ./username.txt
echo -n '1f2d1e2e67df' > ./password.txt

cat <<EOF >./kustomization.yaml
secretGenerator:
- name: example-secret-1
  files:
  - password.txt
EOF
  1. mkdir test_dir
  2. cd test_dir
  3. inside the directory test_dir, and create two files:
cat <<EOF >application.properties
FOO=Bar
EOF

cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: example-configmap-1
  files:
  - application.properties
EOF

cat <<EOF >./kustomization.yaml
secretGenerator:
- name: database-creds
  files:
  - username.txt
EOF

so under test_dir,there are two files created.

4.run: kubectl kustomize ./

5. kubectl apply -k ./

Patch : https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/

secrets : created.

kubectl describe secret secretname

kubectl get secrets

Secrets: Type of secrets and its usecase:

https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets-as-files-from-a-pod

a. VolumeMount : secret -myScrets : if two have keys. and then will create two files under :/etc/foo

(Inside the container that mounts a secret volume, the secret keys appear as files. The secret values are base64 decoded and stored inside these files.)

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
  volumes:
  - name: foo
    secret:
      secretName: mysecret
      defaultMode: 0400

so in order to make decisive of the MountPath

could be :

 volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: mysecret
      items:
      - key: username
        path: my-group/my-username

Get into a container that running in one POD

kubectl exec -i -t PODNAME — /bin/bash

kubectl exec envar-demo — printenv

Above command is to list the ENV in the POD

Use Pod fields as values for environment variables: https://kubernetes.io/docs/tasks/inject-data-application/environment-variable-expose-pod-information/

   env:
        - name: MY_NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        - name: MY_POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: MY_POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: MY_POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: MY_POD_SERVICE_ACCOUNT
          valueFrom:
            fieldRef:
              fieldPath: spec.serviceAccountName
  restartPolicy: Never

StatefulSet: https://kubernetes.io/docs/tasks/run-application/run-replicated-stateful-application/

Learn Kubernetes /Openshift -Notes

https://kubernetes.io/docs/tutorials/

https://kubernetes.io/docs/tutorials/kubernetes-basics/deploy-app/deploy-interactive/

Notes from learning :

Object Names and IDs

Each object in your cluster has a Name that is unique for that type of resource. Every Kubernetes object also has a UID that is unique across your whole cluster.

For example, you can only have one Pod named myapp-1234 within the same namespace, but you can have one Pod and one Deployment that are each named myapp-1234.

For non-unique user-provided attributes, Kubernetes provides labels and annotations

Labels vs Annotations:

Labels are key/value pairs that are attached to objects, such as pods. Labels are intended to be used to specify identifying attributes of objects that are meaningful and relevant to users, but do not directly imply semantics to the core system. Labels can be used to organize and to select subsets of objects. Labels can be attached to objects at creation time and subsequently added and modified at any time. Each object can have a set of key/value labels defined. Each Key must be unique for a given object.

Labels allow for efficient queries and watches and are ideal for use in UIs and CLIs. Non-identifying information should be recorded using annotations

namespace:

Namespaces and DNS 

When you create a Service, it creates a corresponding DNS entry. This entry is of the form <service-name>.<namespace-name>.svc.cluster.local, which means that if a container only uses <service-name>, it will resolve to the service which is local to a namespace. This is useful for using the same configuration across multiple namespaces such as Development, Staging and Production. If you want to reach across namespaces, you need to use the fully qualified domain name (FQDN).

Containers:

Each node in a Kubernetes cluster runs the containers that form the Pods assigned to that node. Containers in a Pod are co-located and co-scheduled to run on the same node

Container image:

Image names 

Container images are usually given a name such as pauseexample/mycontainer, or kube-apiserver. Images can also include a registry hostname; for example: fictional.registry.example/imagename, and possibly a port number as well; for example: fictional.registry.example:10443/imagename.

If you don’t specify a registry hostname, Kubernetes assumes that you mean the Docker public registry.

Container runtimes

The container runtime is the software that is responsible for running containers.

Pods in a Kubernetes cluster are used in two main ways:

  • Pods that run a single container. The “one-container-per-Pod” model is the most common Kubernetes use case; in this case, you can think of a Pod as a wrapper around a single container; Kubernetes manages Pods rather than managing the containers directly.
  • Pods that run multiple containers that need to work together. A Pod can encapsulate an application composed of multiple co-located containers that are tightly coupled and need to share resources. These co-located containers form a single cohesive unit of service—for example, one container serving data stored in a shared volume to the public, while a separate sidecar container refreshes or updates those files. The Pod wraps these containers, storage resources, and an ephemeral network identity together as a single unit.
  • Note: Grouping multiple co-located and co-managed containers in a single Pod is a relatively advanced use case. You should use this pattern only in specific instances in which your containers are tightly coupled.(airflow – etc)

Each Pod is meant to run a single instance of a given application. If you want to scale your application horizontally (to provide more overall resources by running more instances), you should use multiple Pods, one for each instance. In Kubernetes, this is typically referred to as replication. Replicated Pods are usually created and managed as a group by a workload resource and its controller.

Using init containers

Because init containers have separate images from app containers, they have some advantages for start-up related code:

  • Init containers can contain utilities or custom code for setup that are not present in an app image. For example, there is no need to make an image FROM another image just to use a tool like sedawkpython, or dig during setup.
  • The application image builder and deployer roles can work independently without the need to jointly build a single app image.
  • Init containers can run with a different view of the filesystem than app containers in the same Pod. Consequently, they can be given access to Secrets that app containers cannot access.
  • Because init containers run to completion before any app containers start, init containers offer a mechanism to block or delay app container startup until a set of preconditions are met. Once preconditions are met, all of the app containers in a Pod can start in parallel.
  • Init containers can securely run utilities or custom code that would otherwise make an app container image less secure. By keeping unnecessary tools separate you can limit the attack surface of your app container image

Example:

https://kubernetes.io/docs/concepts/workloads/pods/init-containers/

two init-containers need to in runing status before the app container

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app.kubernetes.io/name: MyApp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]

Working with Pods 

Link: https://kubernetes.io/docs/concepts/workloads/pods/

You’ll rarely create individual Pods directly in Kubernetes—even singleton Pods. This is because Pods are designed as relatively ephemeral, disposable entities. When a Pod gets created (directly by you, or indirectly by a controller), the new Pod is scheduled to run on a Node in your cluster. The Pod remains on that node until the Pod finishes execution, the Pod object is deleted, the Pod is evicted for lack of resources, or the node fails.

Note: Restarting a container in a Pod should not be confused with restarting a Pod. A Pod is not a process, but an environment for running container(s). A Pod persists until it is deleted.

Workload

Deployments

ReplicaSet :(the purpose to have replicaset?)

https://www.kubermatic.com/blog/introduction-to-kubernetes-replicasets/

A ReplicaSet is a process that runs multiple instances of a Pod and keeps the specified number of Pods constant. Its purpose is to maintain the specified number of Pod instances running in a cluster at any given time to prevent users from losing access to their application when a Pod fails or is inaccessible.  

ReplicaSet helps bring up a new instance of a Pod when the existing one fails, scale it up when the running instances are not up to the specified number, and scale down or delete Pods if another instance with the same label is created. A ReplicaSet ensures that a specified number of Pod replicas are running continuously and helps with load-balancing in case of an increase in resource usage.

StatefulSet

https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/

1.Headless Services: clusterIP:None  
clusterIP: None
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx

ClusterIP provides a single IP address for the set of Pods the Service is pointing to. This IP address is accessible only within the cluster.

Job: usecase?

The Job object can be used to support reliable parallel execution of Pods. The Job object is not designed to support closely-communicating parallel processes, as commonly found in scientific computing. It does support parallel processing of a set of independent but related work items. These might be emails to be sent, frames to be rendered, files to be transcoded, ranges of keys in a NoSQL database to scan, and so on.

Note: For those platforms that support Pods running in the host network (e.g. Linux), when pods are attached to the host network of a node they can still communicate with all pods on all nodes without NAT.

Kubernetes IP addresses exist at the Pod scope – containers within a Pod share their network namespaces – including their IP address and MAC address. This means that containers within a Pod can all reach each other’s ports on localhost. This also means that containers within a Pod must coordinate port usage, but this is no different from processes in a VM. This is called the “IP-per-pod” model.

Kubernetes networking addresses four concerns:

Example to understand the services:

Service: A Kubernetes Service that identifies a set of Pods using label selectors.

https://kubernetes.io/docs/tutorials/services/connect-applications-service/

Expose the services:

Exposing the Service

For some parts of your applications you may want to expose a Service onto an external IP address. Kubernetes supports two ways of doing this: NodePorts and LoadBalancers. The Service created in the last section already used NodePort, so your nginx HTTPS replica is ready to serve traffic on the internet if your node has a public IP.

A Kubernetes Service is an abstraction which defines a logical set of Pods running somewhere in your cluster, that all provide the same functionality. When created, each Service is assigned a unique IP address (also called clusterIP). This address is tied to the lifespan of the Service, and will not change while the Service is alive. Pods can be configured to talk to the Service, and know that communication to the Service will be automatically load-balanced out to some pod that is a member of the Service.

This specification will create a Service which targets TCP port 80 on any Pod with the run: my-nginx label, and expose it on an abstracted Service port (targetPort: is the port the container accepts traffic on, port: is the abstracted Service port, which can be any port other pods use to access the Service). View Service API object to see the list of supported fields in service definition. Check your Service: