Merge "[COMMON] Create templates for services and PV"
authorBorislav Glozman <Borislav.Glozman@amdocs.com>
Thu, 6 Feb 2020 08:46:04 +0000 (08:46 +0000)
committerGerrit Code Review <gerrit@onap.org>
Thu, 6 Feb 2020 08:46:04 +0000 (08:46 +0000)
14 files changed:
docs/oom_developer_guide.rst
kubernetes/common/cassandra/templates/backup/cronjob.yaml
kubernetes/common/cassandra/templates/pv.yaml
kubernetes/common/cassandra/templates/service.yaml
kubernetes/common/cassandra/templates/statefulset.yaml
kubernetes/common/cassandra/values.yaml
kubernetes/common/common/templates/_labels.tpl [new file with mode: 0644]
kubernetes/common/common/templates/_name.tpl
kubernetes/common/common/templates/_pod.tpl [new file with mode: 0644]
kubernetes/common/common/templates/_service.tpl
kubernetes/common/common/templates/_storage.tpl [moved from kubernetes/common/common/templates/_storageClass.tpl with 63% similarity]
kubernetes/common/common/templates/_tplValue.tpl [new file with mode: 0644]
kubernetes/onap/values.yaml
kubernetes/sdc/values.yaml

index a2ccc1b..c3fb603 100644 (file)
@@ -79,159 +79,123 @@ have been created following the guidelines provided.
 
 The top level of the ONAP charts is shown below:
 
-.. graphviz::
+.. code-block:: bash
+
+  common
+  ├── cassandra
+  │   ├── Chart.yaml
+  │   ├── requirements.yaml
+  │   ├── resources
+  │   │   ├── config
+  │   │   │   └── docker-entrypoint.sh
+  │   │   ├── exec.py
+  │   │   └── restore.sh
+  │   ├── templates
+  │   │   ├── backup
+  │   │   │   ├── configmap.yaml
+  │   │   │   ├── cronjob.yaml
+  │   │   │   ├── pv.yaml
+  │   │   │   └── pvc.yaml
+  │   │   ├── configmap.yaml
+  │   │   ├── pv.yaml
+  │   │   ├── service.yaml
+  │   │   └── statefulset.yaml
+  │   └── values.yaml
+  ├── common
+  │   ├── Chart.yaml
+  │   ├── templates
+  │   │   ├── _createPassword.tpl
+  │   │   ├── _ingress.tpl
+  │   │   ├── _labels.tpl
+  │   │   ├── _mariadb.tpl
+  │   │   ├── _name.tpl
+  │   │   ├── _namespace.tpl
+  │   │   ├── _repository.tpl
+  │   │   ├── _resources.tpl
+  │   │   ├── _secret.yaml
+  │   │   ├── _service.tpl
+  │   │   ├── _storage.tpl
+  │   │   └── _tplValue.tpl
+  │   └── values.yaml
+  ├── ...
+  └── postgres-legacy
+      ├── Chart.yaml
+      ├── requirements.yaml
+      ├── charts
+      └── configs
 
-   digraph onap_top_chart {
-      rankdir="LR";
-      {
-        node      [shape=folder]
-        oValues   [label="values.yaml"]
-        oChart    [label="Chart.yaml"]
-        dev       [label="dev.yaml"]
-        prod      [label="prod.yaml"]
-        crb       [label="clusterrolebindings.yaml"]
-        secrets   [label="secrets.yaml"]
-      }
-      {
-        node      [style=dashed]
-        vCom      [label="component"]
-      }
+The common section of charts consists of a set of templates that assist with
+parameter substitution (`_name.tpl`, `_namespace.tpl` and others) and a set of charts
+for components used throughout ONAP.  When the common components are used by other charts they
+are instantiated each time or we can deploy a shared instances for several components.
 
-      onap         -> oValues
-      onap         -> oChart
-      onap         -> templates
-      onap         -> resources
-      oValues      -> vCom
-      resources    -> environments
-      environments -> dev
-      environments -> prod
-      templates    -> crb
-      templates    -> secrets
-   }
+All of the ONAP components have charts that follow the pattern shown below:
 
-Within the `values.yaml` file at the `onap` level, one will find a set of
-boolean values that control which of the ONAP components get deployed as shown
-below:
+.. code-block:: bash
+
+  name-of-my-component
+  ├── Chart.yaml
+  ├── requirements.yaml
+  ├── component
+  │   └── subcomponent-folder
+  ├── charts
+  │   └── subchart-folder
+  ├── resources
+  │   ├── folder1
+  │   │   ├── file1
+  │   │   └── file2
+  │   └── folder1
+  │       ├── file3
+  │       └── folder3
+  │           └── file4
+  ├── templates
+  │   ├── NOTES.txt
+  │   ├── configmap.yaml
+  │   ├── deployment.yaml
+  │   ├── ingress.yaml
+  │   ├── job.yaml
+  │   ├── secrets.yaml
+  │   └── service.yaml
+  └── values.yaml
+
+Note that the component charts / components may include a hierarchy of sub
+components and in themselves can be quite complex.
+
+You can use either `charts` or `components` folder for your subcomponents.
+`charts` folder means that the subcomponent will always been deployed.
+
+`components` folders means we can choose if we want to deploy the sub component.
+
+This choice is done in root `values.yaml`:
 
 .. code-block:: yaml
 
-  aaf: # Application Authorization Framework
-    enabled: false
-  <...>
-  so: # Service Orchestrator
-    enabled: true
-
-By setting these flags a custom deployment can be created and used during
-deployment by using the `-f` Helm option as follows::
-
-  > helm install local/onap -name development -f dev.yaml
-
-Note that there are one or more example deployment files in the
-`onap/resources/environments/` directory. It is best practice to create a
-unique deployment file for each environment used to ensure consistent
-behaviour.
-
-To aid in the long term supportability of ONAP, a set of common charts have
-been created (and will be expanded in subsequent releases of ONAP) that can be
-used by any of the ONAP components by including the common component in its
-`requirements.yaml` file. The common components are arranged as follows:
-
-.. graphviz::
-
-   digraph onap_common_chart {
-      rankdir="LR";
-      {
-         node      [shape=folder]
-         mValues   [label="values.yaml"]
-         ccValues  [label="values.yaml"]
-         comValues [label="values.yaml"]
-         comChart  [label="Chart.yaml"]
-         ccChart   [label="Chart.yaml"]
-         mChart    [label="Chart.yaml"]
-
-         mReq      [label="requirements.yaml"]
-         mService  [label="service.yaml"]
-         mMap      [label="configmap.yaml"]
-         ccName    [label="_name.tpl"]
-         ccNS      [label="_namespace.tpl"]
-      }
-      {
-         cCom       [label="common"]
-         mTemp      [label="templates"]
-         ccTemp     [label="templates"]
-      }
-      {
-         more       [label="...",style=dashed]
-      }
-
-      common -> comValues
-      common -> comChart
-      common -> cCom
-      common -> mysql
-      common -> more
-
-      cCom   -> ccChart
-      cCom   -> ccValues
-      cCom   -> ccTemp
-      ccTemp -> ccName
-      ccTemp -> ccNS
-
-      mysql  -> mValues
-      mysql  -> mChart
-      mysql  -> mReq
-      mysql  -> mTemp
-      mTemp  -> mService
-      mTemp  -> mMap
-   }
+  ---
+  global:
+    key: value
 
-The common section of charts consists of a set of templates that assist with
-parameter substitution (`_name.tpl` and `_namespace.tpl`) and a set of charts
-for components used throughout ONAP. Initially `mysql` is in the common area
-but this will expand to include other databases like `mariadb-galera`,
-`postgres`, and `cassandra`. Other candidates for common components include
-`redis` and`kafka`.  When the common components are used by other charts they
-are instantiated each time. In subsequent ONAP releases some of the common
-components could be a setup as services that are used by multiple ONAP
-components thus minimizing the deployment and operational costs.
-
-All of the ONAP components have charts that follow the pattern shown below:
-
-.. graphviz::
-
-   digraph onap_component_chart {
-      rankdir="LR";
-      {
-         node      [shape=folder]
-         cValues   [label="values.yaml"]
-         cChart    [label="Chart.yaml"]
-         cService  [label="service.yaml"]
-         cMap      [label="configmap.yaml"]
-         cFiles    [label="config file(s)"]
-      }
-      {
-         cCharts   [label="charts"]
-         cTemp     [label="templates"]
-         cRes      [label="resources"]
+  component1:
+    enabled: true
+  component2:
+    enabled: true
 
-      }
-      {
-         sCom       [label="component",style=dashed]
-      }
+Then in `requirements.yaml`, you'll use these values:
 
-      component -> cValues
-      component -> cChart
-      component -> cCharts
-      component -> cTemp
-      component -> cRes
-      cTemp     -> cService
-      cTemp     -> cMap
-      cRes      -> config
-      config    -> cFiles
-      cCharts   -> sCom
-   }
+.. code-block:: yaml
 
-Note that the component charts may include a hierarchy of components and in
-themselves can be quite complex.
+  ---
+  dependencies:
+    - name: common
+      version: ~x.y-0
+      repository: '@local'
+    - name: component1
+      version: ~x.y-0
+      repository: 'file://components/component1'
+      condition: component1.enabled
+    - name: component2
+      version: ~x.y-0
+      repository: 'file://components/component2'
+      condition: component2.enabled
 
 Configuration of the components varies somewhat from component to component but
 generally follows the pattern of one or more `configmap.yaml` files which can
@@ -260,126 +224,134 @@ configuration as well as ONAP components configuration.
 
 One of the artifacts that OOM/Kubernetes uses to deploy ONAP components is the
 deployment specification, yet another yaml file.  Within these deployment specs
-are a number of parameters as shown in the following mariadb example:
+are a number of parameters as shown in the following example:
 
 .. code-block:: yaml
 
-  apiVersion: extensions/v1beta1
-  kind: Deployment
+  apiVersion: apps/v1
+  kind: StatefulSet
   metadata:
-    name: mariadb
+    labels:
+      app.kubernetes.io/name: zookeeper
+      helm.sh/chart: zookeeper
+      app.kubernetes.io/component: server
+      app.kubernetes.io/managed-by: Tiller
+      app.kubernetes.io/instance: onap-oof
+    name: onap-oof-zookeeper
+    namespace: onap
   spec:
-     <...>
+    <...>
+    replicas: 3
+    selector:
+      matchLabels:
+        app.kubernetes.io/name: zookeeper
+        app.kubernetes.io/component: server
+        app.kubernetes.io/instance: onap-oof
+    serviceName: onap-oof-zookeeper-headless
     template:
-      <...>
+      metadata:
+        labels:
+          app.kubernetes.io/name: zookeeper
+          helm.sh/chart: zookeeper
+          app.kubernetes.io/component: server
+          app.kubernetes.io/managed-by: Tiller
+          app.kubernetes.io/instance: onap-oof
       spec:
-        hostname: mariadb
+        <...>
+        affinity:
         containers:
-        - args:
-          image: nexus3.onap.org:10001/mariadb:10.1.11
-          name: "mariadb"
-          env:
-            - name: MYSQL_ROOT_PASSWORD
-              value: password
-            - name: MARIADB_MAJOR
-              value: "10.1"
+        - name: zookeeper
+          <...>
+          image: gcr.io/google_samples/k8szk:v3
+          imagePullPolicy: Always
           <...>
-        imagePullSecrets:
-        - name: onap-docker-registry-key
-
-Note that within the deployment specification, one of the container arguments
-is the key/value pair image: nexus3.onap.org:10001/mariadb:10.1.11 which
-specifies the version of the mariadb software to deploy.  Although the
-deployment specifications greatly simplify deployment, maintenance of the
-deployment specifications themselves become problematic as software versions
+          ports:
+          - containerPort: 2181
+            name: client
+            protocol: TCP
+          - containerPort: 3888
+            name: election
+            protocol: TCP
+          - containerPort: 2888
+            name: server
+            protocol: TCP
+          <...>
+
+Note that within the statefulset specification, one of the container arguments
+is the key/value pair image: gcr.io/google_samples/k8szk:v3 which
+specifies the version of the zookeeper software to deploy.  Although the
+statefulset specifications greatly simplify statefulset, maintenance of the
+statefulset specifications themselves become problematic as software versions
 change over time or as different versions are required for different
-deployments.  For example, if the R&D team needs to deploy a newer version of
+statefulsets.  For example, if the R&D team needs to deploy a newer version of
 mariadb than what is currently used in the production environment, they would
-need to clone the deployment specification and change this value.  Fortunately,
+need to clone the statefulset specification and change this value.  Fortunately,
 this problem has been solved with the templating capabilities of Helm.
 
-The following example shows how the deployment specifications are modified to
+The following example shows how the statefulset specifications are modified to
 incorporate Helm templates such that key/value pairs can be defined outside of
-the deployment specifications and passed during instantiation of the component.
+the statefulset specifications and passed during instantiation of the component.
 
 .. code-block:: yaml
 
-  apiVersion: extensions/v1beta1
-  kind: Deployment
+  apiVersion: apps/v1
+  kind: StatefulSet
   metadata:
-    name: mariadb
-    namespace: "{{ .Values.nsPrefix }}-mso"
+    name: {{ include "common.fullname" . }}
+    namespace: {{ include "common.namespace" . }}
+    labels: {{- include "common.labels" . | nindent 4 }}
   spec:
+    replicas: {{ .Values.replicaCount }}
+    selector:
+      matchLabels: {{- include "common.matchLabels" . | nindent 6 }}
+    # serviceName is only needed for StatefulSet
+    # put the postfix part only if you have add a postfix on the service name
+    serviceName: {{ include "common.servicename" . }}-{{ .Values.service.postfix }}
     <...>
     template:
-      <...>
+      metadata:
+        labels: {{- include "common.labels" . | nindent 8 }}
+        annotations: {{- include "common.tplValue" (dict "value" .Values.podAnnotations "context" $) | nindent 8 }}
+        name: {{ include "common.name" . }}
       spec:
-        hostname: mariadb
-        containers:
-        - args:
-          image: {{ .Values.image.mariadb }}
-          imagePullPolicy: {{ .Values.pullPolicy }}
-          name: "mariadb"
-          env:
-            - name: MYSQL_ROOT_PASSWORD
-              value: password
-            - name: MARIADB_MAJOR
-              value: "10.1"
         <...>
-        imagePullSecrets:
-        - name: "{{ .Values.nsPrefix }}-docker-registry-key"apiVersion: extensions/v1beta1
-  kind: Deployment
-  metadata:
-    name: mariadb
-    namespace: "{{ .Values.nsPrefix }}-mso"
-  spec:
-    <...>
-    template:
-      <...>
-      spec:
-        hostname: mariadb
         containers:
-        - args:
-          image: {{ .Values.image.mariadb }}
-          imagePullPolicy: {{ .Values.pullPolicy }}
-          name: "mariadb"
-          env:
-            - name: MYSQL_ROOT_PASSWORD
-              value: password
-            - name: MARIADB_MAJOR
-              value: "10.1"
-        <...>
-        imagePullSecrets:
-        - name: "{{ .Values.nsPrefix }}-docker-registry-key"
-
-This version of the deployment specification has gone through the process of
-templating values that are likely to change between deployments. Note that the
-image is now specified as: image: {{ .Values.image.mariadb }} instead of a
-string used previously.  During the deployment phase, Helm (actually the Helm
+          - name: {{ include "common.name" . }}
+            image: {{ .Values.image }}
+            imagePullPolicy: {{ .Values.global.pullPolicy | default .Values.pullPolicy }}
+            ports:
+            {{- range $index, $port := .Values.service.ports }}
+              - containerPort: {{ $port.port }}
+                name: {{ $port.name }}
+            {{- end }}
+            {{- range $index, $port := .Values.service.headlessPorts }}
+              - containerPort: {{ $port.port }}
+                name: {{ $port.name }}
+            {{- end }}
+            <...>
+
+This version of the statefulset specification has gone through the process of
+templating values that are likely to change between statefulsets. Note that the
+image is now specified as: image: {{ .Values.image }} instead of a
+string used previously.  During the statefulset phase, Helm (actually the Helm
 sub-component Tiller) substitutes the {{ .. }} entries with a variable defined
 in a values.yaml file.  The content of this file is as follows:
 
 .. code-block:: yaml
 
-  nsPrefix: onap
-  pullPolicy: IfNotPresent
-  image:
-    readiness: oomk8s/readiness-check:2.0.0
-    mso: nexus3.onap.org:10001/openecomp/mso:1.0-STAGING-latest
-    mariadb: nexus3.onap.org:10001/mariadb:10.1.11
+  <...>
+  image: gcr.io/google_samples/k8szk:v3
+  replicaCount: 3
+  <...>
+
 
-Within the values.yaml file there is an image section with the key/value pair
-mariadb: nexus3.onap.org:10001/mariadb:10.1.11 which is the same value used in
+Within the values.yaml file there is an image key with the value
+`gcr.io/google_samples/k8szk:v3` which is the same value used in
 the non-templated version.  Once all of the substitutions are complete, the
-resulting deployment specification ready to be used by Kubernetes.
-
-Also note that in this example, the namespace key/value pair is specified in
-the values.yaml file.  This key/value pair will be global across the entire
-ONAP deployment and is therefore a prime example of where configuration
-hierarchy can be very useful.
+resulting statefulset specification ready to be used by Kubernetes.
 
-When creating a deployment template consider the use of default values if
-appropriate.  Helm templating has built in support for DEFAULT values, here is
+When creating a template consider the use of default values if appropriate.
+Helm templating has built in support for DEFAULT values, here is
 an example:
 
 .. code-block:: yaml
@@ -394,6 +366,227 @@ Helm template language is a superset of the Go template language).  These
 functions include simple string operations like upper and more complex flow
 control operations like if/else.
 
+OOM is mainly helm templating. In order to have consistent deployment of the
+different components of ONAP, some rules must be followed.
+
+Templates are provided in order to create Kubernetes resources (Secrets,
+Ingress, Services, ...) or part of Kubernetes resources (names, labels,
+resources requests and limits, ...).
+
+Service template
+----------------
+
+In order to create a Service for a component, you have to create a file (with
+`service` in the name.
+For normal service, just put the following line:
+
+.. code-block:: yaml
+
+  {{ include "common.service" . }}
+
+For headless service, the line to put is the following:
+
+.. code-block:: yaml
+
+  {{ include "common.headlessService" . }}
+
+The configuration of the service is done in component `values.yaml`:
+
+.. code-block:: yaml
+
+  service:
+   name: NAME-OF-THE-SERVICE
+   postfix: MY-POSTFIX
+   type: NodePort
+   annotations:
+     someAnnotationsKey: value
+   ports:
+   - name: tcp-MyPort
+     port: 5432
+     nodePort: 88
+   - name: http-api
+     port: 8080
+     nodePort: 89
+   - name: https-api
+     port: 9443
+     nodePort: 90
+
+`annotations` and `postfix` keys are optional.
+if `service.type` is `NodePort`, then you have to give `nodePort` value for your
+service ports (which is the end of the computed nodePort, see example).
+
+It would render the following Service Resource (for a component named
+`name-of-my-component`, with version `x.y.z`, helm deployment name
+`my-deployment` and `global.nodePortPrefix` `302`):
+
+.. code-block:: yaml
+
+  apiVersion: v1
+  kind: Service
+  metadata:
+    annotations:
+      someAnnotationsKey: value
+    name: NAME-OF-THE-SERVICE-MY-POSTFIX
+    labels:
+      app.kubernetes.io/name: name-of-my-component
+      helm.sh/chart: name-of-my-component-x.y.z
+      app.kubernetes.io/instance: my-deployment-name-of-my-component
+      app.kubernetes.io/managed-by: Tiller
+  spec:
+    ports:
+      - port: 5432
+        targetPort: tcp-MyPort
+        nodePort: 30288
+      - port: 8080
+        targetPort: http-api
+        nodePort: 30289
+      - port: 9443
+        targetPort: https-api
+        nodePort: 30290
+    selector:
+      app.kubernetes.io/name: name-of-my-component
+      app.kubernetes.io/instance:  my-deployment-name-of-my-component
+    type: NodePort
+
+In the deployment or statefulSet file, you needs to set the good labels in order
+for the service to match the pods.
+
+here's an example to be sure it matchs (for a statefulSet):
+
+.. code-block:: yaml
+
+  apiVersion: apps/v1
+  kind: StatefulSet
+  metadata:
+    name: {{ include "common.fullname" . }}
+    namespace: {{ include "common.namespace" . }}
+    labels: {{- include "common.labels" . | nindent 4 }}
+  spec:
+    selector:
+      matchLabels: {{- include "common.matchLabels" . | nindent 6 }}
+    # serviceName is only needed for StatefulSet
+    # put the postfix part only if you have add a postfix on the service name
+    serviceName: {{ include "common.servicename" . }}-{{ .Values.service.postfix }}
+    <...>
+    template:
+      metadata:
+        labels: {{- include "common.labels" . | nindent 8 }}
+        annotations: {{- include "common.tplValue" (dict "value" .Values.podAnnotations "context" $) | nindent 8 }}
+        name: {{ include "common.name" . }}
+      spec:
+       <...>
+       containers:
+         - name: {{ include "common.name" . }}
+           ports:
+           {{- range $index, $port := .Values.service.ports }}
+           - containerPort: {{ $port.port }}
+             name: {{ $port.name }}
+           {{- end }}
+           {{- range $index, $port := .Values.service.headlessPorts }}
+           - containerPort: {{ $port.port }}
+             name: {{ $port.name }}
+           {{- end }}
+           <...>
+
+The configuration of the service is done in component `values.yaml`:
+
+.. code-block:: yaml
+
+  service:
+   name: NAME-OF-THE-SERVICE
+   headless:
+     postfix: NONE
+     annotations:
+       anotherAnnotationsKey : value
+     publishNotReadyAddresses: true
+   headlessPorts:
+   - name: tcp-MyPort
+     port: 5432
+   - name: http-api
+     port: 8080
+   - name: https-api
+     port: 9443
+
+`headless.annotations`, `headless.postfix` and
+`headless.publishNotReadyAddresses` keys are optional.
+
+If `headless.postfix` is not set, then we'll add `-headless` at the end of the
+service name.
+
+If it set to `NONE`, there will be not postfix.
+
+And if set to something, it will add `-something` at the end of the service
+name.
+
+It would render the following Service Resource (for a component named
+`name-of-my-component`, with version `x.y.z`, helm deployment name
+`my-deployment` and `global.nodePortPrefix` `302`):
+
+.. code-block:: yaml
+
+  apiVersion: v1
+  kind: Service
+  metadata:
+    annotations:
+      anotherAnnotationsKey: value
+    name: NAME-OF-THE-SERVICE
+    labels:
+      app.kubernetes.io/name: name-of-my-component
+      helm.sh/chart: name-of-my-component-x.y.z
+      app.kubernetes.io/instance: my-deployment-name-of-my-component
+      app.kubernetes.io/managed-by: Tiller
+  spec:
+    clusterIP: None
+    ports:
+      - port: 5432
+        targetPort: tcp-MyPort
+        nodePort: 30288
+      - port: 8080
+        targetPort: http-api
+        nodePort: 30289
+      - port: 9443
+        targetPort: https-api
+        nodePort: 30290
+    publishNotReadyAddresses: true
+    selector:
+      app.kubernetes.io/name: name-of-my-component
+      app.kubernetes.io/instance:  my-deployment-name-of-my-component
+    type: ClusterIP
+
+Previous example of StatefulSet would also match (except for the `postfix` part
+obviously).
+
+Creating Deployment or StatefulSet
+----------------------------------
+
+Deployment and StatefulSet should use the `apps/v1` (which has appeared in
+v1.9).
+As seen on the service part, the following parts are mandatory:
+
+.. code-block:: yaml
+
+  apiVersion: apps/v1
+  kind: StatefulSet
+  metadata:
+    name: {{ include "common.fullname" . }}
+    namespace: {{ include "common.namespace" . }}
+    labels: {{- include "common.labels" . | nindent 4 }}
+  spec:
+    selector:
+      matchLabels: {{- include "common.matchLabels" . | nindent 6 }}
+    # serviceName is only needed for StatefulSet
+    # put the postfix part only if you have add a postfix on the service name
+    serviceName: {{ include "common.servicename" . }}-{{ .Values.service.postfix }}
+    <...>
+    template:
+      metadata:
+        labels: {{- include "common.labels" . | nindent 8 }}
+        annotations: {{- include "common.tplValue" (dict "value" .Values.podAnnotations "context" $) | nindent 8 }}
+        name: {{ include "common.name" . }}
+      spec:
+        <...>
+        containers:
+          - name: {{ include "common.name" . }}
 
 ONAP Application Configuration
 ------------------------------
@@ -423,18 +616,16 @@ SO deployment specification excerpt:
 
 .. code-block:: yaml
 
-  apiVersion: extensions/v1beta1
+  apiVersion: apps/v1
   kind: Deployment
   metadata:
-    name: {{ include "common.name" . }}
+    name: {{ include "common.fullname" . }}
     namespace: {{ include "common.namespace" . }}
-    labels:
-      app: {{ include "common.name" . }}
-      chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
-      release: {{ .Release.Name }}
-      heritage: {{ .Release.Service }}
+    labels: {{- include "common.labels" . | nindent 4 }}
   spec:
     replicas: {{ .Values.replicaCount }}
+    selector:
+      matchLabels: {{- include "common.matchLabels" . | nindent 6 }}
     template:
       metadata:
         labels:
index 2edc807..e4f2aab 100644 (file)
@@ -19,11 +19,7 @@ kind: CronJob
 metadata:
   name: {{ include "common.fullname" . }}-backup
   namespace: {{ include "common.namespace" . }}
-  labels:
-    app: {{ include "common.fullname" . }}
-    chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
-    release: {{ include "common.release" . }}
-    heritage: {{ .Release.Service }}
+  labels: {{- include "common.labels" . | nindent 4 }}
 spec:
   schedule: {{ .Values.backup.cron | quote }}
   concurrencyPolicy: Forbid
@@ -31,6 +27,10 @@ spec:
   jobTemplate:
     spec:
       template:
+        metadata:
+          labels: {{- include "common.labels" . | nindent 12 }}
+          annotations: {{- include "common.tplValue" (dict "value" .Values.podAnnotations "context" .) | nindent 12 }}
+          name: {{ include "common.name" . }}
         spec:
           restartPolicy: Never
           initContainers:
index fd0a758..76a224a 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-{{- $global := . }}
-{{- if and $global.Values.persistence.enabled (not $global.Values.persistence.existingClaim) }}
-{{- if eq "True" (include "common.needPV" .) -}}
-{{- range $i := until (int $global.Values.replicaCount)}}
----
-apiVersion: v1
-kind: PersistentVolume
-metadata:
-  name: {{ include "common.release" $global }}-{{ $global.Values.service.name }}-{{ $i }}
-  namespace: {{ $global.Release.Namespace }}
-  labels:
-    type: {{ $global.Values.persistence.storageType }}
-    app: {{ $global.Values.service.name }}
-    chart: {{ $global.Chart.Name }}-{{ $global.Chart.Version | replace "+" "_" }}
-    release: {{ include "common.release" $global }}
-    heritage: {{ $global.Release.Service }}
-spec:
-  capacity:
-    storage: {{ $global.Values.persistence.size }}
-  accessModes:
-  {{- if $global.Values.backup.enabled }}
-  - ReadWriteMany
-  {{- else }}
-  - ReadWriteOnce
-  {{- end }}
-  persistentVolumeReclaimPolicy: {{ $global.Values.persistence.volumeReclaimPolicy }}
-  storageClassName: "{{ include "common.fullname" $global }}-data"
-  hostPath:
-    path: {{ $global.Values.persistence.mountPath }}/{{ include "common.release" $global }}/{{ $global.Values.persistence.mountSubPath }}-{{ $i }}
-{{- end -}}
-{{- end -}}
-{{- end -}}
+{{ include "common.replicaPV" . }}
index 6cbddbe..0b91076 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-apiVersion: v1
-kind: Service
-metadata:
-  name: {{ include "common.servicename" . }}
-  namespace: {{ include "common.namespace" . }}
-  labels:
-    app: {{ include "common.name" . }}
-    chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
-    release: {{ include "common.release" . }}
-    heritage: {{ .Release.Service }}
-  annotations:
-    service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
-spec:
-  type: {{ .Values.service.type }}
-  publishNotReadyAddresses: true
-  ports:
-  {{if eq .Values.service.type "NodePort" -}}
-  {{- $global := . }}
-  {{- range $index, $ports := .Values.service.ports }}
-  - port: {{ $ports.port }}
-    targetPort: {{ $ports.port }}
-    nodePort: {{ $global.Values.global.nodePortPrefix | default $global.Values.nodePortPrefix }}{{ $ports.nodePort }}
-    name: {{ $ports.name }}
-  {{- end }}
-{{- else -}}
-  {{- range $index, $ports := .Values.service.ports }}
-  - port: {{ $ports.port }}
-    targetPort: {{ $ports.port }}
-    name: {{ $ports.name }}
-  {{- end }}
-{{- end}}
-  selector:
-    app: {{ include "common.name" . }}
-    release: {{ include "common.release" . }}
-  clusterIP: None
+{{ include "common.headlessService" . }}
index b737a8f..16aa27f 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-apiVersion: apps/v1beta1
+apiVersion: apps/v1
 kind: StatefulSet
-metadata:
-  name: {{ include "common.fullname" . }}
-  namespace: {{ include "common.namespace" . }}
-  labels:
-    app: {{ include "common.name" . }}
-    chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
-    release: {{ include "common.release" . }}
-    heritage: {{ .Release.Service }}
+metadata: {{- include "common.resourceMetadata" . | nindent 2 }}
 spec:
-  selector:
-    matchLabels:
-      app: {{ include  "common.name" . }}
-      release: {{ include "common.release" . }}
+  selector: {{- include "common.selectors" . | nindent 4 }}
   serviceName: {{ include "common.servicename" . }}
   replicas: {{ .Values.replicaCount }}
   podManagementPolicy: {{ .Values.podManagementPolicy }}
   updateStrategy:
     type: {{ .Values.updateStrategy.type }}
   template:
-    metadata:
-      labels:
-        app: {{ include "common.name" . }}
-        release: {{ include "common.release" . }}
-      name: {{ include "common.name" . }}
+    metadata: {{- include "common.templateMetadata" . | nindent 6 }}
     spec:
       hostNetwork: {{ .Values.hostNetwork }}
       containers:
       - name: {{ include "common.name" . }}
         image: {{ .Values.image }}
         imagePullPolicy: {{ .Values.global.pullPolicy | default .Values.pullPolicy }}
-        ports:
-        {{- range $index, $ports := .Values.service.ports }}
-        - containerPort: {{ $ports.port }}
-        {{- end }}
+        ports: {{ include "common.containerPorts" . | nindent 8  }}
         volumeMounts:
           - name: {{ include "common.fullname" . }}-data
             mountPath: /var/lib/cassandra
index c3af7e5..dfa0a3e 100644 (file)
@@ -75,22 +75,27 @@ readiness:
   failureThreshold: 3
 
 service:
-  type: ClusterIP
   name: cassandra
-  ports:
-  - name: intra
+  headless:
+    suffix: ""
+    annotations:
+      service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
+    publishNotReadyAddresses: true
+  headlessPorts:
+  - name: tcp-intra
     port: 7000
   - name: tls
     port: 7001
-  - name: jmx
+  - name: tcp-jmx
     port: 7199
-  - name: cql
+  - name: tcp-cql
     port: 9042
-  - name: thrift
+  - name: tcp-thrift
     port: 9160
-  - name: agent
+  - name: tcp-agent
     port: 61621
 
+podAnnotations: {}
 podManagementPolicy: OrderedReady
 updateStrategy:
   type: RollingUpdate
@@ -116,7 +121,7 @@ persistence:
   ##
   ## storageClass: "-"
   ## Not set as it depends of the backup enabledment or not.
-  #accessMode: ReadWriteOnce
+  accessMode: ReadWriteOnce
   size: 2Gi
   mountPath: /dockerdata-nfs
   mountSubPath: cassandra
diff --git a/kubernetes/common/common/templates/_labels.tpl b/kubernetes/common/common/templates/_labels.tpl
new file mode 100644 (file)
index 0000000..95d51e1
--- /dev/null
@@ -0,0 +1,62 @@
+{{/*
+# Copyright © 2019 Orange
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+*/}}
+
+
+
+{{/*
+Common labels
+*/}}
+{{- define "common.labels" -}}
+app.kubernetes.io/name: {{ include "common.name" . }}
+helm.sh/chart: {{ include "common.chart" . }}
+app.kubernetes.io/instance: {{ include "common.release" . }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end -}}
+
+{{/*
+Labels to use on deploy.spec.selector.matchLabels and svc.spec.selector
+*/}}
+{{- define "common.matchLabels" -}}
+app.kubernetes.io/name: {{ include "common.name" . }}
+app.kubernetes.io/instance: {{ include "common.release" . }}
+{{- end -}}
+
+{{/*
+  Generate "top" metadata for Deployment / StatefulSet / ...
+*/}}
+{{- define "common.resourceMetadata" -}}
+name: {{ include "common.fullname" . }}
+namespace: {{ include "common.namespace" . }}
+labels: {{- include "common.labels" . | nindent 2 }}
+{{- end -}}
+
+{{/*
+  Generate selectors for Deployment / StatefulSet / ...
+*/}}
+{{- define "common.selectors" -}}
+matchLabels: {{- include "common.matchLabels" . | nindent 2 }}
+{{- end -}}
+
+{{/*
+  Generate "template" metadata for Deployment / StatefulSet / ...
+*/}}
+{{- define "common.templateMetadata" -}}
+{{- if .Values.podAnnotations }}
+annotations: {{- include "common.tplValue" (dict "value" .Values.podAnnotations "context" $) | nindent 2 }}
+{{- end }}
+labels: {{- include "common.labels" . | nindent 2 }}
+name: {{ include "common.name" . }}
+{{- end -}}
index 7719cdb..943078f 100644 (file)
@@ -49,3 +49,7 @@
 {{- define "common.release" -}}
   {{- first (regexSplit "-" .Release.Name -1)  }}
 {{- end -}}
+
+{{- define "common.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
diff --git a/kubernetes/common/common/templates/_pod.tpl b/kubernetes/common/common/templates/_pod.tpl
new file mode 100644 (file)
index 0000000..9329572
--- /dev/null
@@ -0,0 +1,38 @@
+{{/*
+# Copyright © 2019 Orange
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+*/}}
+
+{{/*
+  Generate the container port list.
+  Will use first ".Values.service.ports" list.
+  Will append ports from ".Values.service.headlessPorts" only if port number is
+  not already in port list.
+*/}}
+{{- define "common.containerPorts" -}}
+{{-   $ports := default (list) .Values.service.ports }}
+{{-   $portsNumber := list }}
+{{-   range $index, $port := $ports }}
+{{-     $portsNumber = append $portsNumber $port.port }}
+{{-   end }}
+{{-   range $index, $port := .Values.service.headlessPorts }}
+{{-     if not (has $port.port $portsNumber) }}
+{{-       $ports = append $ports $port }}
+{{-     end }}
+{{-   end }}
+{{-   range $index, $port := $ports }}
+- containerPort: {{ $port.port }}
+  name: {{ $port.name }}
+{{-   end }}
+{{- end -}}
index 77b77d0..075f796 100644 (file)
@@ -20,7 +20,7 @@
   The default will be the chart name (or .Values.nameOverride if set).
   And the use of .Values.service.name overrides all.
 
-  - .Values.service.name  : override default service (ie. chart) name
+  - .Values.service.name: override default service (ie. chart) name
 */}}
 {{/*
   Expand the service name for a chart.
 {{- define "common.servicename" -}}
   {{- $name := default .Chart.Name .Values.nameOverride -}}
   {{- default $name .Values.service.name | trunc 63 | trimSuffix "-" -}}
-{{- end -}}
\ No newline at end of file
+{{- end -}}
+
+{{/* Define the metadata of Service
+     The function takes from one to three arguments (inside a dictionary):
+     - .dot : environment (.)
+     - .suffix : a string which will be added at the end of the name (with a '-').
+     - .annotations: the annotations to add
+     Usage example:
+      {{ include "common.serviceMetadata" ( dict "suffix" "myService" "dot" .) }}
+      {{ include "common.serviceMetadata" ( dict "annotations" .Values.service.annotation "dot" .) }}
+*/}}
+{{- define "common.serviceMetadata" -}}
+  {{- $dot := default . .dot -}}
+  {{- $suffix := default "" .suffix -}}
+  {{- $annotations := default "" .annotations -}}
+{{- if $annotations -}}
+annotations: {{- include "common.tplValue" (dict "value" $annotations "context" $dot) | nindent 2 }}
+{{- end }}
+name: {{ include "common.servicename" $dot }}{{ if $suffix }}{{ print "-" $suffix }}{{ end }}
+namespace: {{ include "common.namespace" $dot }}
+labels: {{- include "common.labels" $dot | nindent 2 -}}
+{{- end -}}
+
+{{/* Define the ports of Service
+     The function takes three arguments (inside a dictionary):
+     - .dot : environment (.)
+     - .ports : an array of ports
+     - .portType: the type of the service
+*/}}
+{{- define "common.servicePorts" -}}
+{{- $portType := .portType -}}
+{{- $dot := .dot -}}
+{{- range $index, $port := .ports }}
+- port: {{ $port.port }}
+  targetPort: {{ $port.name }}
+  {{- if (eq $portType "NodePort") }}
+  nodePort: {{ $dot.Values.global.nodePortPrefix | default $dot.Values.nodePortPrefix }}{{ $port.nodePort }}
+  {{- end }}
+  name: {{ $port.name }}
+{{- end -}}
+{{- end -}}
+
+{{/* Create generic service template
+     The function takes several arguments (inside a dictionary):
+     - .dot : environment (.)
+     - .ports : an array of ports
+     - .portType: the type of the service
+     - .suffix : a string which will be added at the end of the name (with a '-')
+     - .annotations: the annotations to add
+     - .publishNotReadyAddresses: if we publish not ready address
+     - .headless: if the service is headless
+*/}}
+{{- define "common.genericService" -}}
+{{- $dot := default . .dot -}}
+{{- $suffix := default "" .suffix -}}
+{{- $annotations := default "" .annotations -}}
+{{- $publishNotReadyAddresses := default false .publishNotReadyAddresses -}}
+{{- $portType := .portType -}}
+{{- $ports := .ports -}}
+{{- $headless := default false .headless -}}
+apiVersion: v1
+kind: Service
+metadata: {{ include "common.serviceMetadata" (dict "suffix" $suffix "annotations" $annotations "dot" $dot ) | nindent 2 }}
+spec:
+  {{- if $headless }}
+  clusterIP: None
+  {{- end }}
+  ports: {{- include "common.servicePorts" (dict "portType" $portType "ports" $ports "dot" $dot) | nindent 4 }}
+  {{- if $publishNotReadyAddresses }}
+  publishNotReadyAddresses: true
+  {{- end }}
+  type: {{ $portType }}
+  selector: {{- include "common.matchLabels" $dot | nindent 4 }}
+{{- end -}}
+
+{{/* Create service template */}}
+{{- define "common.service" -}}
+{{- $suffix := default "" .Values.service.suffix -}}
+{{- $annotations := default "" .Values.service.annotations -}}
+{{- $publishNotReadyAddresses := default false .Values.service.publishNotReadyAddresses -}}
+{{- $portType := .Values.service.type -}}
+{{- $ports := .Values.service.ports -}}
+{{ include "common.genericService" (dict "suffix" $suffix "annotations" $annotations "dot" . "publishNotReadyAddresses" $publishNotReadyAddresses "ports" $ports "portType" $portType) }}
+{{- end -}}
+
+{{/* Create headless service template */}}
+{{- define "common.headlessService" -}}
+{{- $suffix := include "common._makeHeadlessSuffix" . -}}
+{{- $annotations := default "" .Values.service.headless.annotations -}}
+{{- $publishNotReadyAddresses := default false .Values.service.headless.publishNotReadyAddresses -}}
+{{- $ports := .Values.service.headlessPorts -}}
+{{ include "common.genericService" (dict "suffix" $suffix "annotations" $annotations "dot" . "publishNotReadyAddresses" $publishNotReadyAddresses "ports" $ports "portType" "ClusterIP" "headless" true ) }}
+{{- end -}}
+
+{{/*
+  Generate the right suffix for headless service
+*/}}
+{{- define "common._makeHeadlessSuffix" -}}
+{{-   if hasKey .Values.service.headless "suffix" }}
+{{-     .Values.service.headless.suffix }}
+{{-   else }}
+{{-     print "headless" }}
+{{-   end }}
+{{- end -}}
   Calculate if we need a PV. If a storageClass is provided, then we don't need.
 */}}
 {{- define "common.needPV" -}}
-{{- if or (or .Values.persistence.storageClassOverride .Values.persistence.storageClass) .Values.global.persistence.storageClass -}}
-  False
-{{- else -}}
+{{- if not (or (or .Values.persistence.storageClassOverride .Values.persistence.storageClass) .Values.global.persistence.storageClass) -}}
   True
 {{- end -}}
 {{- end -}}
+
+{{/*
+  Generate N PV for a statefulset
+*/}}
+{{- define "common.replicaPV" -}}
+{{- $global := . }}
+{{- if and $global.Values.persistence.enabled (not $global.Values.persistence.existingClaim) }}
+{{- if (include "common.needPV" .) -}}
+{{- range $i := until (int $global.Values.replicaCount)}}
+---
+kind: PersistentVolume
+apiVersion: v1
+metadata:
+  name: {{ include "common.fullname" $global }}-data-{{$i}}
+  namespace: {{ include "common.namespace" $global }}
+  labels: {{- include "common.labels" $global | nindent 4 }}
+spec:
+  capacity:
+    storage: {{ $global.Values.persistence.size}}
+  accessModes:
+    - {{ $global.Values.persistence.accessMode }}
+  persistentVolumeReclaimPolicy: {{ $global.Values.persistence.volumeReclaimPolicy }}
+  storageClassName: "{{ include "common.fullname" $global }}-data"
+  hostPath:
+    path: {{ $global.Values.global.persistence.mountPath | default $global.Values.persistence.mountPath }}/{{ include "common.release" $global }}/{{ $global.Values.persistence.mountSubPath }}-{{$i}}
+{{- end -}}
+{{- end -}}
+{{- end -}}
+{{- end -}}
diff --git a/kubernetes/common/common/templates/_tplValue.tpl b/kubernetes/common/common/templates/_tplValue.tpl
new file mode 100644 (file)
index 0000000..b74ecbd
--- /dev/null
@@ -0,0 +1,28 @@
+{{/*
+# Copyright © 2019 Orange
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+*/}}
+
+{{/*
+Renders a value that contains template.
+Usage:
+{{ include "common.tplValue" ( dict "value" .Values.path.to.the.Value "context" $) }}
+*/}}
+{{- define "common.tplValue" -}}
+    {{- if typeIs "string" .value }}
+        {{- tpl .value .context }}
+    {{- else }}
+        {{- tpl (.value | toYaml) .context }}
+    {{- end }}
+{{- end -}}
index 5344a42..2395495 100755 (executable)
@@ -173,4 +173,4 @@ vid:
 vnfsdk:
   enabled: false
 modeling:
-  enabled: false
\ No newline at end of file
+  enabled: false
index a7006bc..6abf911 100644 (file)
@@ -29,7 +29,7 @@ global:
   ubuntuInitRepository: oomk8s
   ubuntuInitImage: ubuntu-init:1.0.0
   cassandra:
-   #This flag allows SDC to instantiate its own cluster, serviceName 
+   #This flag allows SDC to instantiate its own cluster, serviceName
    #should be sdc-cs if this flag is enabled
    localCluster: false
    #The cassandra service name to connect to (default: shared cassandra service)