Apps entwickeln

Entwickeln Sie eine Konfiguration für die Bereitstellung Ihrer App-Workload in IBM Cloud® Kubernetes Service. Da Kubernetes eine erweiterbare Containerorchestrierungsplattform ist, die keine bestimmte Sprache oder App voraussetzt, können Sie verschiedene Workloads wie statusunabhängige und statusabhängige Apps sowie Datenverarbeitungsapps ausführen, die in der Sprache Ihrer Wahl geschrieben sind.

App-Anforderungen in YAML-Datei angeben

In Kubernetes beschreiben Sie die App in einer YAML-Datei, durch die die Konfiguration des Kubernetes-Objekts deklariert wird. Anschließend wird die YAML-Datei vom Kubernetes-API-Server verarbeitet und die Konfiguration und der erforderliche Status des Objekts werden im Datenspeicher 'etcd' gespeichert. Der Kubernetes-Scheduler plant die Workloads auf den Workerknoten im Cluster und berücksichtigt dabei die Spezifikation in der YAML-Datei, alle vom Administrator festgelegten Clusterrichtlinien und die verfügbare Clusterkapazität.

Sehen Sie sich eine Kopie der vollständigen YAML-Datei an. Überprüfen Sie danach die folgenden Abschnitte, um zu untersuchen, wie Sie die Bereitstellung der App verbessern können.

Benötigen Sie weitere Informationen zum Zusammenspiel von Kubernetes-Objekten für Ihre Bereitstellung? Ziehen Sie dann den Abschnitt mit den Erläuterungen zu Kubernetes-Objekten für Apps zurate.

Basismetadaten einer Bereitstellung

Verwenden Sie die geeignete API-Version für die Art des Kubernetes-Objekts, das Sie bereitstellen. Von der API-Version hängt ab, welche Funktionen für das Kubernetes-Objekt unterstützt werden und Ihnen somit zur Verfügung stehen. Der Name, den Sie in den Metadaten angeben, ist der Name des Objekts, nicht die Bezeichnung. Sie verwenden den Namen bei der Interaktion mit Ihrem Objekt, z. B. kubectl get deployment <name>.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: wasliberty

Replikatgruppe

Wenn Sie die Verfügbarkeit der App erhöhen möchten, können Sie eine Replikatgruppe in der Bereitstellung angeben. In einer Replikatgruppe definieren Sie, wie viele Instanzen der App bereitgestellt werden sollen. Replikatgruppen werden von der Kubernetes-Bereitstellung verwaltet und überwacht. Wenn eine App-Instanz inaktiv wird, wird von Kubernetes automatisch eine neue Instanz der App aktiviert, damit die angegebene Anzahl der App-Instanzen erhalten bleibt.

spec:
  replicas: 3

Bezeichnungen

Mit Bezeichnungen können Sie verschiedene Ressourcentypen im Cluster mit demselben Schlüssel/Wert-Paar (key: value) markieren. Anschließend können Sie den Selektor für die Übereinstimmung der Bezeichnung angeben, sodass Sie auf dieser Basis andere Ressourcen erstellen können. Wenn Sie die App öffentlich zugänglich machen möchten, müssen Sie eine Bezeichnung verwenden, die mit dem Selektor übereinstimmt, den Sie im Service angeben. Im Beispiel verwendet die Bereitstellungsspezifikation die Vorlage, die mit der Bezeichnung übereinstimmt app: wasliberty.

Sie können Objekte abrufen, die im Cluster gekennzeichnet sind, um zum Beispiel die Komponenten staging oder production anzuzeigen. Beispiel: Listen Sie alle Ressourcen mit der Bezeichnung env: production für alle Namensbereiche im Cluster auf. Hinweis: Sie benötigen Zugriff auf alle Namensbereiche, um diesen Befehl ausführen zu können.

kubectl get all -l env=production --all-namespaces
selector:
  matchLabels:
    app: wasliberty
template:
  metadata:
    labels:
      app: wasliberty

Affinität

Geben Sie die Affinität (Colocation) an, wenn Sie mehr Kontrolle darüber wünschen, auf welchen Worker-Knoten die Pods eingeplant werden. Die Affinität wirkt sich nur während der Planzeit auf die Pods aus. Beispiel: Wenn Sie die Bereitstellung auf Workerknoten verteilen möchten, anstatt den Pods das Planen auf demselben Knoten zu ermöglichen, verwenden Sie die Option podAntiAffinity mit den Standardclustern. Sie können zwei Typen von Pod-Anti-Affinität definieren: bevorzugt oder erforderlich.

Weitere Informationen finden Sie in der Dokumentation zu Kubernetes unter Pods zu Knoten zuweisen.

Erforderliche Anti-Affinität
Sie können nur die Anzahl an Replikaten bereitstellen, für die Workerknoten vorhanden sind. Wenn Sie beispielsweise drei Workerknoten haben, aber in Ihrer YAML-Datei fünf Replikate definieren, werden nur drei Replikate bereitgestellt. Jedes Replikat befindet sich auf einem anderen Workerknoten. Die zwei übrigen Replikate verbleiben ausstehend. Wenn Sie einen weiteren Workerknoten zu Ihrem Cluster hinzufügen, wird eines der restlichen Replikate automatisch auf dem Workerknoten bereitgestellt. Wenn ein Workerknoten ausfällt, wird der Pod nicht neu geplant, da eine Affinitätsrichtlinie erforderlich ist. Ein Beispiel für YAML mit der Anforderung required finden Sie unter Liberty-App mit erforderlicher Pod-Anti-Affinität.
Bevorzugte Anti-Affinität
Sie können Ihre Pods auf Knoten mit verfügbarer Kapazität bereitstellen und auf diese Weise eine größere Flexibilität in Bezug auf Ihre Workload erlangen. Wenn möglich, werden die Pods auf verschiedenen Workerknoten geplant. Wenn Sie beispielsweise über drei Workerknoten mit ausreichend Kapazität im Cluster verfügen, können fünf Replikatknoten für die Knoten geplant werden. Wenn Sie Ihrem Cluster jedoch zwei weitere Worker-Knoten hinzufügen, zwingt die Affinitätsregel die beiden zusätzlichen Pods, die auf den bestehenden Knoten laufen, nicht dazu, auf den verfügbaren Knoten neu eingeplant zu werden.
Workerknotenaffinität
Sie können Ihre Bereitstellung so konfigurieren, dass nur bestimmte Workerknoten ausgeführt werden, z. B. Bare-Metal-Workerknoten. Weitere Informationen finden Sie unter Apps für bestimmte Workerknoten mithilfe von Bezeichnungen bereitstellen.

Beispiel für bevorzugte Anti-Affinität

spec:
  affinity:
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - wasliberty
          topologyKey: kubernetes.io/hostname

Container-Image

Geben Sie das Image, das Sie für die Container verwenden möchten, die Position des Image und die Extrahierungsrichtlinie für das Image an. Wenn Sie kein Image-Tag angeben, wird standardmäßig das Image mit der Kennung latestextrahiert.

Vermeiden Sie die Verwendung des Tags 'Latest' für Produktionsworkloads. Es kann vorkommen, dass Sie die Workload nicht mit dem neuesten Image getestet haben, wenn Sie ein öffentliches oder ein gemeinsames Repository verwenden, z. B. Docker Hub oder IBM Cloud Container Registry.

Gehen Sie zum Beispiel zum Auflisten der Tags von öffentlichen IBM Images wie folgt vor:

  1. Wechseln Sie zur Region der globalen Registry.
    ibmcloud cr region-set global
    
  2. Listen Sie die IBM-Images auf.
    ibmcloud cr images --include-ibm
    

Als Standardwert für imagePullPolicy ist IfNotPresent festgelegt, was bedeutet, dass das Image nur extrahiert wird, wenn es nicht lokal vorhanden ist. Wenn das Image bei jedem Start des Containers extrahiert werden soll, geben Sie imagePullPolicy: Always an.

containers:
- name: wasliberty
  image: icr.io/ibm/liberty:webProfile8
  imagePullPolicy: Always

Port für den Service der App

Wählen Sie einen Container-Port aus, an dem die Services der App geöffnet werden sollen. Informationen dazu, welcher Port geöffnet werden muss, finden Sie in den Spezifikationen zur App oder in der Dockerfile. Der Zugriff auf den Port ist über das private Netz möglich, aber nicht über eine öffentliche Netzverbindung. Um die App öffentlich zugänglich zu machen, müssen Sie einen NodePort-Service, Service für eine Lastausgleichsfunktion oder Ingress-Service erstellen. Sie verwenden dieselbe Portnummer, wenn Sie ein Objekt des Typs Service erstellen.

Der Port 25 ist für alle Services in IBM Cloud blockiert.

ports:
- containerPort: 9080

Ressourcenanforderungen und -grenzwerte

Cluster-Administratoren stellen sicher, dass Teams, die sich einen Cluster teilen, nicht mehr als ihren gerechten Anteil an Rechenressourcen (Arbeitsspeicher und CPU) beanspruchen, indem sie für jeden Kubernetes-Namespace im Cluster ein Objekt ResourceQuota anlegen. Wenn der Clusteradministrator eine Datenverarbeitungsressourcenquote definiert, müssen von jedem Container in der Bereitstellungsvorlage Ressourcenanforderungen und -begrenzungen für Speicher und CPU angegeben werden; andernfalls schlägt die Erstellung des Pods fehl.

  1. Überprüfen Sie, ob eine Ressourcenquote für einen Namensbereich festgelegt ist.
    kubectl get quota --namespace=<namespace>
    
  2. Überprüfen Sie die Werte für die Größenbeschränkungen.
    kubectl describe quota <quota_name> --namespace=<namespace>
    

Auch wenn keine Ressourcenquote festgelegt ist, können Sie Ressourcenanforderungen und -begrenzungen in die Bereitstellung einschließen, um die Verwaltung der Workerknotenressourcen zu verbessern.

Wenn ein Container seinen Grenzwert überschreitet, kann der Container erneut gestartet werden oder fehlschlagen. Wenn ein Container eine Anforderung überschreitet, wird sein Pod möglicherweise entfernt, falls diese Ressource für den Workerknoten knapp wird. Fehlerbehebungsinformationen finden Sie unter Neustarts von Pods schlagen wiederholt fehl oder Pods werden unerwartet entfernt.

Anforderung
Der Mindestressourcenumfang, den der Scheduler für die Nutzung durch den Container reserviert. Wenn die Menge mit dem Grenzwert übereinstimmt, wird die Anforderung garantiert. Wenn die Menge niedriger als der Grenzwert ist, wird die Anforderung auch garantiert, aber der Scheduler kann die Differenz zwischen der Anforderung und dem Grenzwert zum Erfüllen von Anforderungen für Ressourcen anderer Container verwenden.
Grenzwert
Der maximale Ressourcenumfang, den der Container nutzen kann. Wenn die Gesamtmenge der Ressourcen, die für die Container verwendet wird, die auf dem Workerknoten verfügbare Menge überschreitet, können Container entfernt werden, um Speicherplatz frei zu machen. Wenn Sie eine Entfernung verhindern möchten, legen Sie fest, dass die Ressourcenanforderung mit dem Grenzwert des Containers identisch ist. Wenn kein Grenzwert angegeben ist, ist der Standardwert die Kapazität des Workerknotens.

Weitere Informationen finden Sie in der Dokumentation zu Kubernetes.

resources:
  requests:
    memory: "512Mi"
    cpu: "500m"
  limits:
    memory: "1024Mi"
    cpu: "1000m"

Aktivitäts- und Bereitschaftsprüfungen

Standardmäßig sendet Kubernetes Datenverkehr an die App-Pods, nachdem alle Container im Pod gestartet wurden, und startet die Container bei einem Absturz erneut. Sie können jedoch Statusprüfungen festlegen, um die Zuverlässigkeit der Weiterleitung für den Datenverkehr des Service zu verbessern.

Es kann zum Beispiel vorkommen, dass es beim Starten der App zu einer Verzögerung kommt. Die App-Prozesse können beginnen, bevor die gesamte App vollständig bereit ist, was Antworten beeinträchtigen kann, insbesondere wenn viele Instanzen skaliert werden. Anhand der Statusprüfungen kann vom System erkannt werden, ob eine App aktiv und zum Empfang von Anforderungen bereit ist. Wenn Sie solche Tests einrichten, können Sie auch dazu beitragen, Ausfallzeiten zu verhindern, falls Sie eine rollierende Aktualisierung der App ausführen. Sie können zwei Arten von Statusprüfungen festlegen: Aktivitäts- und Bereitschaftsprüfungen.

Aktivitätsprüfung
Richten Sie eine Aktivitätsprüfung ein, um zu überprüfen, ob der Container ausgeführt wird. Wenn die Prüfung fehlschlägt, wird der Container erneut gestartet. Wenn für den Container keine Aktivitätsprüfung angegeben ist, verläuft der Test erfolgreich, da davon ausgegangen wird, dass der Container aktiv ist, wenn sich der Container im Status Aktiv befindet.
Bereitschaftsprüfung
Richten Sie eine Bereitschaftsprüfung ein, um zu überprüfen, ob der Container Anforderungen und externen Datenverkehr empfangen kann. Wenn die Prüfung fehlschlägt, wird die IP-Adresse des Pods als verwendbare IP-Adresse für Services entfernt, die mit dem Pod übereinstimmen, aber der Container wird nicht erneut gestartet. Das Einrichten einer Bereitschaftsprüfung mit einer anfänglichen Verzögerung ist besonders wichtig, wenn der Start Ihrer App eine Weile dauert. Da die Prüfung vor der Anfangsverzögerung nicht ausgeführt wird, reicht die Zeit für das Starten des Containers aus. Wenn für den Container keine Bereitschaftsprüfung angegeben ist, verläuft der Test erfolgreich, da davon ausgegangen wird, dass der Container aktiv ist, wenn sich der Container im Status Aktiv befindet.

Sie können die Prüfungen als Befehle, HTTP-Anforderungen oder TCP-Sockets einrichten. Im Beispiel werden HTTP-Anforderungen verwendet. Legen Sie für die Aktivitätsprüfung mehr Zeit als für die Bereitschaftsprüfung fest. Weitere Informationen finden Sie in der Dokumentation zu Kubernetes.

livenessProbe:
  httpGet:
    path: /
    port: 9080
  initialDelaySeconds: 300
  periodSeconds: 15
readinessProbe:
  httpGet:
    path: /
    port: 9080
  initialDelaySeconds: 45
  periodSeconds: 5

Budget für den Podausfall

Um die Verfügbarkeit Ihrer App zu erhöhen, können Sie mithilfe eines Objekts PodDisruptionBudget steuern, wie Ihre App auf Störungen reagiert, je nachdem, welche Art von Verfügbarkeit Sie anstreben.

Mit einem Budget für den Podausfall können Sie planen, wie sich Ihre App bei beabsichtigten Ausfällen, z. B. durch das Initiieren eines direkten Neustarts durch eine Aktualisierung der App-Bereitstellung, und bei unbeabsichtigten Ausfällen, z. B. durch eine Kernelpanik, verhält. minAvailable : Sie können die Anzahl oder den Prozentsatz der Pods angeben, die nach dem Auftreten einer Unterbrechung weiterhin verfügbar sein müssen.

maxUnavailable
Sie können die Anzahl oder den Prozentsatz der Pods angeben, die nach dem Auftreten einer Unterbrechung nicht verfügbar sein dürfen. Im Beispiel wird die Einstellung maxUnavailable: 1 verwendet.
selector
Geben Sie das Label ein, um die Gruppe von Pods auszuwählen, auf die dies PodDisruptionBudget zutrifft. Dabei ist zu beachten Sie, dass bei Angabe einer Bezeichnung, die auch in anderen Pod-Bereitstellungen verwendet wird, auch diese Bereitstellungen berücksichtigt werden.

Weitere Informationen finden Sie in der Dokumentation zu Kubernetes.

apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: wasliberty
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app: wasliberty

App-Service zugänglich machen

Sie können einen Service erstellen, von dem die App verfügbar gemacht wird. Stellen Sie im Abschnitt spec sicher, dass die Werte für port und die Bezeichnungswerte mit denen übereinstimmen, die in der Bereitstellung verwendet werden. Vom Service werden Objekte verfügbar gemacht, die mit der Bezeichnung übereinstimmen, zum Beispiel app: wasliberty im folgenden Beispiel.

  • Standardmäßig verwendet ein Dienst ClusterIP, wodurch der Dienst nur innerhalb des Clusters, nicht jedoch außerhalb des Clusters zugänglich ist.
  • Sie können einen NodePort-Service, Service für eine Lastausgleichsfunktion oder Ingress-Service erstellen, um die App öffentlich zugänglich zu machen. Diese Services verfügen über zwei IPs, eine externe und eine interne. Wenn der Datenverkehr an der externen IP empfangen wird, wird er an die interne Cluster-IP weitergeleitet. Anschließend wird der Datenverkehr von der internen Cluster-IP an die Container-IP der App weitergeleitet.
  • Im Beispiel wird NodePort verwendet, um den Service außerhalb des Clusters zugänglich zu machen. Weitere Informationen zum Festlegen des externen Zugriffs finden Sie unter NodePort-Service, Service für Lastausgleichsfunktion oder Ingress-Service auswählen.
apiVersion: v1
kind: Service
metadata:
  name: wasliberty
  labels:
    app: wasliberty
spec:
  ports:
  - port: 9080
  selector:
    app: wasliberty
    type: NodePort

Wenn Sie hostNetwork-Pods bereitstellen müssen, die an bestimmten Ports empfangsbereit sind, oder einen hostPort verwenden müssen, um Ihre App-Pods über einen bestimmten Port auf dem Workerknoten zugänglich zu machen, verwenden Sie einen Port im Bereich 11000-11200. IBM Cloud Kubernetes Service legt für diesen Zweck den Portbereich 11000-11200 auf Workerknoten fest, um Konflikte mit lokalen Ports und anderen, von IBM Cloud Kubernetes Service verwendeten Ports zu vermeiden. Da sich hostNetwork-Pods und hostPorts auf die IP-Adresse eines bestimmten Workerknotens beziehen, können die Pods nur auf diesem Workerknoten ausgeführt werden. Wenn ein unerwarteter Fehler auftritt, z. B. wenn der Workerknoten entfernt wird oder nicht mehr genügend Ressourcen zur Verfügung stehen, kann Ihr Pod nicht neu geplant werden. Wenn Sie den Port eines Pods auf dem Workerknoten zugänglich machen möchten, sollten Sie stattdessen einen NodePort-Service verwenden. Weitere Informationen finden Sie in der Dokumentation Kubernetes zu bewährten Verfahren.

Konfigurationszuordnungen für Containerumgebungsvariablen

Von Konfigurationszuordnungen werden nicht sensible Konfigurationsdaten für Bereitstellungsworkloads zur Verfügung gestellt.

Im folgenden Beispiel wird veranschaulicht, wie Sie Werte der Konfigurationszuordnung als Umgebungsvariablen im Abschnitt für die Containerspezifikation der YAML-Bereitstellungsdatei referenzieren können. Wenn Sie Werte aus der Konfigurationszuordnung referenzieren, können Sie diese Konfigurationsdaten von der Bereitstellung entkoppeln, damit die containerisierte App portierbar bleibt.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: wasliberty
spec:
  replicas: 3
  template:
    ...
    spec:
      ...
      containers:
      - name: wasliberty
        ...
        env:
          - name: VERSION
            valueFrom:
              configMapKeyRef:
                name: wasliberty
                key: VERSION
          - name: LANGUAGE
            valueFrom:
              configMapKeyRef:
                name: wasliberty
                key: LANGUAGE
        ...
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: wasliberty
  labels:
    app: wasliberty
data:
  VERSION: "1.0"
  LANGUAGE: en

Geheime Schlüssel für Containerumgebungsvariablen

Von geheimen Schlüsseln werden Konfigurationsinformationen wie zum Beispiel Kennwörter für die Workloads von Bereitstellungen bereitgestellt.

Im folgenden Beispiel wird veranschaulicht, wie Sie Werte aus dem geheimen Schlüssel als Umgebungsvariablen im Abschnitt mit der Containerspezifikation der YAML-Bereitstellungsdatei referenzieren können. Sie können den geheimen Schlüssel auch als Datenträger anhängen. Wenn Sie Werte aus dem geheimen Schlüssel referenzieren, können Sie diese Konfigurationsdaten von der Bereitstellung entkoppeln, damit die containerisierte App portierbar bleibt.

Für die zentrale Verwaltung all Ihrer Geheimnisse in verschiedenen Clustern und die Injektion zur App-Laufzeit empfiehlt sich IBM Cloud Secrets Manager.

apiVersion: apps/v1
  kind: Deployment
  metadata:
    name: wasliberty
  spec:
    replicas: 3
    template:
      ...
      spec:
        ...
        containers:
        - name: wasliberty
          ...
          env:
          - name: username
            valueFrom:
              secretKeyRef:
                name: wasliberty
                key: username
          - name: password
            valueFrom:
              secretKeyRef:
                name: wasliberty
                key: password
          ...
  ---
  apiVersion: v1
  kind: Secret
  metadata:
    name: wasliberty
    labels:
      app: wasliberty
  type: Opaque
  data:
    username: dXNlcm5hbWU=
    password: cGFzc3dvcmQ=

Persistente Datenträger für Containerspeicher

Persistente Datenträger dienen als Schnittstelle zum physischen Speicher, um einen persistenten Datenspeicher für Container-Workloads bereitzustellen.

Im folgenden Beispiel wird veranschaulicht, wie einer App persistenter Speicher hinzugefügt werden kann. Wenn Sie persistenten Speicher bereitstellen möchten, erstellen Sie einen Persistent Volume Claim (PVC), um den Typ und die Größe des gewünschten Dateispeichers zu beschreiben. Nachdem Sie das PVC erstellt haben, werden das persistente Volume und der physische Speicher mithilfe der dynamischen Bereitstellung automatisch angelegt. Wenn in der YAML-Bereitstellungsdatei auf den PVC verwiesen wird, wird der Speicher automatisch an den App-Pod angehängt. Wenn vom Container im Pod Daten in das Mountpfadverzeichnis /test geschrieben werden, werden die Daten in der NFS-Dateispeicherinstanz gespeichert. Informationen zu Optionen für weitere Speichertypen, die Sie bereitstellen können, finden Sie unter Persistenten Hochverfügbarkeitsspeicher planen.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: wasliberty
spec:
  replicas: 3
  template:
    ...
    spec:
      ...
      containers:
      - name: wasliberty
        ...
        volumeMounts:
        - name: pvmount
          mountPath: /test
      volumes:
      - name: pvmount
        persistentVolumeClaim:
          claimName: wasliberty
        ...
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: wasliberty
  annotations:
    volume.beta.kubernetes.io/storage-class: "ibmc-file-bronze"
  labels:
    billingType: "hourly"
    app: wasliberty
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 24Gi

Beispiel einer vollständigen YAML-Bereitstellungsdatei

Das folgende Beispiel ist eine Kopie einer YAML-Bereitstellungsdatei, die vorher Abschnitt für Abschnitt erläutert wurde. Sie können die YAML-Datei auch unter GitHub herunterladen.

Geben Sie Folgendes ein, um die YAML-Datei anzuwenden:

kubectl apply -f file.yaml [-n <namespace>]

YAML-Beispieldatei

apiVersion: apps/v1
kind: Deployment
metadata:
  name: wasliberty
spec:
  replicas: 3
  selector:
    matchLabels:
      app: wasliberty
  template:
    metadata:
      labels:
        app: wasliberty
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - wasliberty
              topologyKey: kubernetes.io/hostname
      containers:
      - name: wasliberty
        image: icr.io/ibm/liberty:latest
        env:
          - name: VERSION
            valueFrom:
              configMapKeyRef:
                name: wasliberty
                key: VERSION
          - name: LANGUAGE
            valueFrom:
              configMapKeyRef:
                name: wasliberty
                key: LANGUAGE
          - name: username
            valueFrom:
              secretKeyRef:
                name: wasliberty
                key: username
          - name: password
            valueFrom:
              secretKeyRef:
                name: wasliberty
                key: password
        ports:
          - containerPort: 9080
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "1024Mi"
            cpu: "1000m"
        livenessProbe:
          httpGet:
            path: /
            port: 9080
          initialDelaySeconds: 300
          periodSeconds: 15
        readinessProbe:
          httpGet:
            path: /
            port: 9080
          initialDelaySeconds: 45
          periodSeconds: 5
        volumeMounts:
        - name: pvmount
          mountPath: /test
      volumes:
      - name: pvmount
        persistentVolumeClaim:
          claimName: wasliberty
---
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: wasliberty
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app: wasliberty
---
apiVersion: v1
kind: Service
metadata:
  name: wasliberty
  labels:
    app: wasliberty
spec:
  ports:
  - port: 9080
  selector:
    app: wasliberty
  type: NodePort
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: wasliberty
  labels:
    app: wasliberty
data:
  VERSION: "1.0"
  LANGUAGE: en
---
apiVersion: v1
kind: Secret
metadata:
  name: wasliberty
  labels:
    app: wasliberty
type: Opaque
data:
  username: dXNlcm5hbWU=
  password: cGFzc3dvcmQ=
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: wasliberty
  annotations:
    volume.beta.kubernetes.io/storage-class: "ibmc-file-bronze"
  labels:
    billingType: "hourly"
    app: wasliberty
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 24Gi