INDEX
########################################################### 2024-01-06 21:30 ########################################################### That Devops Guy... Kubernetes Ingress: NGINX https://www.youtube.com/watch?v=u948CURLDJA Every service has an entrypoint for traffic (called API gateway or load balancer) This is an "ingress controller" - accepts or denies HTTP traffic (e.g. nginx) SSL termination means it requires tls exernally but internal apps don't use it Also manages URL rewriting, load balancing etc. Kubernetes lets you write ingress config in a universal language - converted for, say, nginx One controller can have many ingresses - define all intended config kubectl create namesapce example-app kubectl apply -n example-app -f deployment.yaml kubectl apply -n example-app -f configmap.yaml kubectl apply -n example-app -f secrets.yaml kubectl apply -n example-app -f service.yaml # Defines how to route traffic to pods kubectl -n example-app get pods kubectl -n example-app port-forward POD_NAME 5000 # Manually port forward to localhost:5000 Need to define the nginx ingress controller service account: # nginx/namespace.yaml apiVersion: v1 kind: Namespace metadata: name: ingress-nginx # nginx/service-account.yaml apiVersion: v1 kind: ServiceAccount metadata: name: nginx-ingress-serviceaccount namespace: ingress-nginx kubectl apply -f nginx/namespace.yaml kubectl apply -f nginx/service-account.yaml Now define the access permissions of that service account # nginx/cluster-role.yaml (defines permissions of this service account) apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole metadata: name: nginx-ingress-clusterrole rules: # Essentially set command access rules for different resources - apiGroups: # Generic access for most resources - "" resources: - configmaps - endpoints - nodes - pods - secrets verbs: - list - watch - apiGroups: # For nodes - "" resources: - nodes verbs: - get - apiGroups: # For services - "" resources: - services verbs: - get - list - watch - apiGroups: # For events - "" resources: - events verbs: - create - patch - apiGroups: # For ingresses (watch and track them) - "extensions" - "networking.k8s.io" resources: - ingresses verbs: - get - list - watch - apiGroups: # For ingress stautus, also allow updating - "extensions" - "networking.k8s.io" resources: - ingresses/status verbs: - update kubectl apply -f nginx/cluster-role.yaml And now bind those access permissions to that service account # nginx/cluster-role-binding.yaml apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: nginx-ingress-clusterrole-nisa-binding roleRef: # Link the cluster role permissions apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: nginx-ingress-clusterrole subjects: # Link to the service account - kind: ServiceAccount name: nginx-ingress-serviceaccount namespace: ingress-nginx kubectl apply -f nginx/cluster-role-binding.yaml # So now the service account has access to do what we want it to For nginx specific, look in kubernetes nginx documentation: "Nginx Config/ConfigMap" # configMap.yaml apiVersion: v1 kind: ConfigMap metadata: name: nginx-configuration namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx data: client-body-buffer-size: 60k client-header-buffer-size: 16k error-log-level: warn http2-max-field-size: 16k large-client-header-buffers: 4 16k log-format-escape-json: "true" log-format-upstream: ... # Long config for log formatting location-snippet: "include /etc/nginx/custom-snippets/location-custom.conf;" --- apiVersion: v1 kind: ConfigMap metadata: # Empty but allows other defined rules name: tcp-services namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx --- apiVersion: v1 kind: ConfigMap metadata: name: udp-services namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx # "location-custom.conf" is a lua script for ingress rules (e.g. cross origin resource share) kubectl apply -f configMap.yaml Once you've applied the nginx configmaps you can apply the main deployment # deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-ingress-controller namespace: nginx-ingress spec: replicas: 2 selector: matchLabels: app: nginx-ingress template: metadata: labels: app: nginx-ingress annotations: prometheus.io/port: "10254" prometheus.io/scrape: "true" spec: serviceAccountName: nginx-ingress-serviceaccount containers: - name: nginx-ingress-controller image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.25.1 args: # Point to all the config maps - /nginx-ingress-controller - --configmaps=$(POD_NAMESPACE)/nginx-configuration - --tcp-service-configmap=$(POD_NAMESPACE)/tcp-services - --udp-service-configmap=$(POD_NAMESPACE)/udp-services - --publish-services=$(POD_NAMESPACE)/ingress-nginx - --annotations-prefix=nginx.ingress.kubernetes.io securityContext: allowPrivelegeEscalation: true capabilities: drop: - ALL add: - NET_BIND_SERVICE runAsUser: 33 volumeMounts: - name: custom-snippets mountPath: /etc/nginx/custom-snippets/ env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace ports: - name: http containerPort: 80 - name: https containerPort: 443 livenessProbe failureThreshold: 3 httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 10 readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 10 volumes: - name: custom-snippets configMap: name: custom-snippets kubectl apply -f deployment.yaml Now run a load balancer service # service.yaml apiVersion: v1 kind: Service metadata: name: ingress-nginx namespace: ingress-nginx spec: externalTrafficPolicy: Local selector: app: nginx-ingress type: LoadBalancer ports: - name: http port: 80 targetPort: http - name: https port: 443 targetPort: https # Also have a self signed TLS certificate for https # tls-secret.yaml apiVersion: v1 kind: Secret metadata: name: marcel-tls-secret namespace: example-app # Running for the application, specifically type: kubernetes.io/tls data: tls.crt: ... tls.key: ... # Now kubernetes will make a load balancer based on what host you're running on kubectl apply -f service.yaml kubectl apply -f tls-secret.yaml Now you have the ingress CONTROLLER defined - you need to define the ingress rules # ingress-nginx-example.yaml apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: "nginx" # Tell Kubernetes this is for nginx nginx.ingress.kubernetes.io/rewrite-target: / # Receive on root path name: example-app namespace: example-app spec: tls: # Enable tls (run on 443) - hosts: - marcel.test secretName: marcel-tls-secret # Point to the ssl secret rules: - host: marcel.test http: paths: - path: /v1/hello backend: serviceName: example-service ServicePort: 80 - path: /v2/hello backend: serviceName: example-service ServicePort: 80 kubectl apply -f ingress-nginx-example.yaml # Can now access the application on "marcel.test/v1/hello" and on "v2"
That Devops Guy... Kubernetes Ingress Explained for Beginners https://www.youtube.com/watch?v=izWCkcJAzBw Ingress is like an API gateway to route traffic into kubernetes services Pods interact through services to other pods, in other deployments/namespaces Ingress controllers can also interact with pods via services (like a gateway) So to configure public access, just configure the ingress controller A developer doesn't need to know how ingresses work - just write yaml for traffic rules