EJECUTAR 1 - Ejecutándose en Kubernetes

Requisitos previos

Para ejecutar este tutorial, usted necesitará ejecutar un kubernetes agrupar localmente: A continuación se presentan algunas opciones posibles que puede utilizar:

Instale y inicie su solución deseada para ejecutar un Kubernetes agrupación local.

Kubernetes(K8s) es un sistema de código abierto para automatizar el despliegue, la escalabilidad y la gestión de aplicaciones en contenedores.

Despliegue del Tutorial de IPF en Kubernetes

Requisitos

Paso 1 - Crear un Espacio de Nombres

kubectl create namespace ipf-tutorial

Paso 2 - Crear Cuenta de Servicio

Cree un 'serviceAccount.yaml' archivo y copie el siguiente manifiesto de cuenta de servicio administrativo.

---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: ipf-tutorial
  namespace: ipf-tutorial
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "watch", "list"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: ipf-tutorial
  namespace: ipf-tutorial
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: ipf-tutorial
  namespace: ipf-tutorial
subjects:
  - kind: ServiceAccount
    name: ipf-tutorial
    namespace: ipf-tutorial
roleRef:
  kind: Role
  name: ipf-tutorial
  apiGroup: rbac.authorization.k8s.io

La 'serviceAccount.yaml' crea un rol de ipf-tutorial, una cuenta de servicio 'ipf-tutorial' y vincula el 'Rol' a la cuenta de servicio.

El rol 'ipf-tutorial' tiene todos los permisos para consultar la API para los pods de IPF que se ejecutan dentro del espacio de nombres.

Ahora cree la cuenta de servicio utilizando kubectl.

kubectl apply -f serviceAccount.yaml

Paso 3 - Crear Configmap

Cree un archivo Configmap llamado 'configmap.yaml y copie el siguiente manifiesto de configuración.

apiVersion: v1
kind: ConfigMap
metadata:
  name: ipf-tutorial-service-cm
  namespace: ipf-tutorial
data:
  application.conf: |
    akka {
      loglevel = "INFO"
      cluster {
        # undefine seed nodes to allow for Kubernetes to describe cluster topography
        seed-nodes = []
        sharding {
          distributed-data.majority-min-cap = 2
        }
      }
      # Use Kubernetes API to discover the cluster
      discovery {
        kubernetes-api {
          pod-label-selector = "app=%s"
        }
      }
      actor.provider = cluster
    }
    akka.remote.artery.canonical.hostname = ${POD_IP}
    akka.management {
      # available from Akka management >= 1. 0. 0
      health-checks {
        readiness-path  = "health/ready"
        liveness-path   = "health/alive"
      }
      # use the Kubernetes API to create the cluster
      cluster.bootstrap {
        contact-point-discovery {
          service-name              = "ipf-tutorial-service"
          discovery-method          = kubernetes-api
          required-contact-point-nr = 2
        }
      }
    }
    management.endpoints.web.exposure.include = "*"
    flow-restart-settings {
      min-backoff = 1s
      max-backoff = 5s
      random-factor = 0. 25
      max-restarts = 5000
      max-restarts-within = 3h
    }
    ipf.behaviour.retries.initial-timeout = 3s
    ipf.behaviour.config.action-recovery-delay = 3s
    #Change the Mongo URL for your specific setup
    ipf {
      mongodb.url = "mongodb://ipf-mongo:27017/ipf"
      processing-data.egress {
        enabled = true
        transport = http
        http {
          client {
            host = "ipf-developer-service"
            port = 8081
            endpoint-url = "/ipf-processing-data"
          }
        }
      }
    }
  logback.xml: |
    <? xml version="1. 0" encoding="UTF-8"?>
    <configuration>
      <appender name="CONSOLE" class="ch.qos.logback.core. ConsoleAppender">
        <target>System.out</target>
        <encoder>
          <pattern>[%date{ISO8601}] [%level] [%logger] [%marker] [%thread] - %msg MDC: {%mdc}%n</pattern>
        </encoder>
      </appender>
      <appender name="ASYNC" class="ch.qos.logback.classic. AsyncAppender">
        <queueSize>8192</queueSize>
        <neverBlock>true</neverBlock>
        <appender-ref ref="CONSOLE" />
      </appender>
      <logger name="akka" level="WARN" />
      <root level="INFO">
        <appender-ref ref="ASYNC"/>
      </root>
    </configuration>

Ahora cree el mapa de configuración utilizando kubectl.

kubectl apply -f configmap.yaml

Paso 4 - Crear imagePullSecret

Sustituir docker-servidor,docker-nombre de usuario y docker-contraseña para valores apropiados
kubectl create secret docker-registry registrysecret --docker-server=**** --docker-username=********* --docker-password=******* --namespace ipf-tutorial

Paso 5 - Crear MongoDB

Cree un archivo de statefulset llamado 'infrastructure'.yaml y copie el siguiente manifiesto. Esto crea MongoDB que es requerido por la aplicación del tutorial

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mongo
  namespace: ipf-tutorial
spec:
  selector:
    matchLabels:
      role: mongo
  serviceName: "ipf-mongo"
  replicas: 1
  template:
    metadata:
      labels:
        role: mongo
    spec:
      imagePullSecrets:
        - name: "registrysecret"
      terminationGracePeriodSeconds: 10
      containers:
        - name: mongo
          image:mongo:latest
          imagePullPolicy: Always
          ports:
            - containerPort: 27017
        - name: mongo-exporter
          image:bitnami/mongodb-exporter:0. 11. 2
          imagePullPolicy: IfNotPresent
          ports:
            - name: mongo-exporter
              containerPort: 9216
              protocol: TCP
          env:
            - name: MONGODB_URI
              value: "mongodb://localhost:27017"
---
apiVersion: v1
kind: Service
metadata:
  name: ipf-mongo
  namespace: ipf-tutorial
  labels:
    name: ipf-mongo
    type: mongo
spec:
  ports:
    - port: 27017
      name: mongo
      protocol: TCP
      targetPort: 27017
  selector:
    role: mongo
kubectl apply -f infrastructure.yaml

Paso 6 - Crear Aplicación para Desarrolladores

Cree un archivo de implementación llamado developerApp.yaml y copie el siguiente manifiesto. Esto crea la aplicación de desarrollador que es requerida por la aplicación tutorial para ver el flujo.events

${registry_service} - sustituto para la ubicación de la docker registro

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ipf-developer-service
  namespace: ipf-tutorial
  annotations:
    prometheus.io/scrape: "true"
    prometheus.io/path: "/"
    prometheus.io/port: "9001"
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ipf-developer-service
      product: ipfv2
  template:
    metadata:
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/path: "/"
        prometheus.io/port: "9001"
      labels:
        app: ipf-developer-service
        product: ipfv2
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: app
                    operator: In
                    values:
                      - ipf-developer-service
              topologyKey: kubernetes.io/hostname
      securityContext:
        fsGroup: 1000
        runAsUser: 1000
      serviceAccountName: ipf-tutorial
      imagePullSecrets:
        - name: "registrysecret"
      containers:
        - name: ipf-developer-service
          image: $\{registry_service}/ipf-developer-app:latest
          imagePullPolicy: Always
          ports:
            - name: actuator
              containerPort: 8081
          env:
            - name: "POD_NAME"
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: "POD_IP"
              valueFrom:
                fieldRef:
                  fieldPath: status.podIP
            - name: "KUBERNETES_NAMESPACE"
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: "IPF_JAVA_ARGS"
              value: "-Dma.glasnost.orika.writeClassFiles=false -Dma.glasnost.orika.writeSourceFiles=false"
          resources:
            limits:
              memory: "2Gi"
            requests:
              memory: "2Gi"
              cpu: "1000m"
          volumeMounts:
            - mountPath: /ipf-developer-app/conf/logback.xml
              name: config-volume
              subPath: logback.xml
            - mountPath: /ipf-developer-app/conf/application.conf
              name: config-volume
              subPath: application.conf
      volumes:
        - name: config-volume
          configMap:
            name: ipf-developer-service-cm
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: ipf-developer-service-cm
  namespace: ipf-tutorial
data:
  application.conf: |
    flow-restart-settings {
     min-backoff = 1s
     max-backoff = 5s
     random-factor = 0.25
     max-restarts = 5
     max-restarts-within = 10m
    }
    spring.data.mongodb.uri = ${?ipf.mongodb.url}
    actor-system-name = ipf-developer
    ipf.mongodb.url = "mongodb://ipf-mongo:27017/ipf"
    ods.security.oauth.enabled = false
    application.write.url="http://localhost:8080"
    ipf.processing-data.ingress.transport=http
  logback.xml: |
    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
      <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <target>System.out</target>
        <encoder>
          <pattern>[%date{ISO8601}] [%level] [%logger] [%marker] [%thread] - %msg MDC: {%mdc}%n</pattern>
        </encoder>
      </appender>
      <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
        <queueSize>8192</queueSize>
        <neverBlock>true</neverBlock>
        <appender-ref ref="CONSOLE" />
      </appender>
      <logger name="akka" level="WARN" />
      <root level="INFO">
        <appender-ref ref="ASYNC"/>
      </root>
    </configuration>
---
apiVersion: v1
kind: Service
metadata:
  name: ipf-developer-service
  namespace: ipf-tutorial
  labels:
    name: ipf-developer-service
spec:
  type: NodePort
  ports:
    - protocol: TCP
      port: 8081
      targetPort: 8081
      nodePort: 30200
      name: ipf-developer-service
  selector:
    app: ipf-developer-service

Paso 7 - Crear un Despliegue

Cree un archivo de implementación llamado 'deployment.yaml y copie el siguiente manifiesto de implementación.

${registry_service} - sustituto para la ubicación de la docker registro ${tutorial-service-version} - versión de la aplicación tutorial

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ipf-tutorial-service
  namespace: ipf-tutorial
  annotations:
    prometheus.io/scrape: "true"
    prometheus.io/path: "/"
    prometheus.io/port: "9001"
spec:
  replicas: 3
  selector:
    matchLabels:
      app: ipf-tutorial-service
      product: ipfv2
  template:
    metadata:
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/path: "/"
        prometheus.io/port: "9001"
      labels:
        app: ipf-tutorial-service
        product: ipfv2
    spec:
      #      affinity:
      #        podAntiAffinity:
      #          requiredDuringSchedulingIgnoredDuringExecution:
      #            - labelSelector:
      #                matchExpressions:
      #                  - key: app
      #                    operator: In
      #                    values:
      #                      - ipf-tutorial-service
      #              topologyKey: kubernetes.io/hostname
      securityContext:
        fsGroup: 1000
        runAsUser: 1000
      serviceAccountName: ipf-tutorial
      imagePullSecrets:
        - name: "registrysecret"
      containers:
        - name: ipf-tutorial-service
          image: ${registry_service}/ipf-tutorial-app:${tutorial-service-version}
          imagePullPolicy: Always
          ports:
            - name: actuator
              containerPort: 8080
            - name: akka-artery
              containerPort: 55001
            - name: akka-management
              containerPort: 8558
            - name: akka-metrics
              containerPort: 9001
          livenessProbe:
            failureThreshold: 5
            httpGet:
              path: /health/alive
              port: akka-management
              scheme: HTTP
            initialDelaySeconds: 30
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 1
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /health/ready
              port: akka-management
              scheme: HTTP
            initialDelaySeconds: 30
            periodSeconds: 10
            successThreshold: 10
            timeoutSeconds: 1
          env:
            - name: "POD_NAME"
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: "POD_IP"
              valueFrom:
                fieldRef:
                  fieldPath: status.podIP
            - name: "KUBERNETES_NAMESPACE"
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: "IPF_JAVA_ARGS"
              value: "-Dma.glasnost.orika.writeClassFiles=false -Dma.glasnost.orika.writeSourceFiles=false"
          resources:
            limits:
              memory: "2Gi"
            requests:
              memory: "2Gi"
              cpu: "1000m"
          volumeMounts:
            - mountPath: /ipf-tutorial-app/conf/logback.xml
              name: config-volume
              subPath: logback.xml
            - mountPath: /ipf-tutorial-app/conf/application.conf
              name: config-volume
              subPath: application.conf
      volumes:
        - name: config-volume
          configMap:
            name: ipf-tutorial-service-cm
---
apiVersion: v1
kind: Service
metadata:
  name: ipf-tutorial-service
  namespace: ipf-tutorial
  labels:
    name: ipf-tutorial-service
spec:
  type: NodePort
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
      nodePort: 30100
      name: ipf-tutorial-service
  selector:
    app: ipf-tutorial-service
las reglas de afinidad (comentadas), si se utilizan, son una forma de especificar dónde/en qué nodos deben estar los pods scheduled. Esto puede ser útil para asegurar que los pods sean scheduled en diferentes nodos, por ejemplo.

En este IPF Kubernetes en la implementación hemos utilizado lo siguiente:

  1. securityContext para el pod de IPF

  2. Sonda de vivacidad y preparación para monitorear la salud del pod IPF.

  3. Archivos de configuración de aplicación y registro almacenados como Kubernetes Elementos de ConfigMap.

Cree la implementación utilizando kubectl.

kubectl apply -f deployment.yaml

Verifique el estado de la implementación.

kubectl get deployments -n ipf-tutorial

Ahora, puede obtener los detalles de implementación utilizando el siguiente comando.

kubectl describe deployments --namespace=ipf-tutorial

Envíe un pago utilizando el siguiente comando.

curl -X POST http://<cluster-node-ip-address>:30100/submit | jq

Verifique el pago en la aplicación para desarrolladores en la siguiente URL.

http://<cluster-node-ip-address>:30200/explorer.html[NOTA]
Consulte la documentación de la opción de clúster elegida sobre cómo obtener la dirección IP del nodo. Algunas opciones posibles son:
'kubectl get nodes -o wide', 'minikube ip'.