diff --git a/examples/wordpress/README.md b/examples/wordpress/README.md new file mode 100644 index 000000000..9e2e57d06 --- /dev/null +++ b/examples/wordpress/README.md @@ -0,0 +1,155 @@ +# Wordpress Example +Welcome to the Wordpress example. It shows you how to deploy a Wordpress application using Deployment Manager. + +## Prerequisites +### Deployment Manager +First, make sure DM is installed in your Kubernetes cluster by following the instructions in the top level +[README.md](../../README.md). + +### Google Cloud Resources +The Wordpress application will make use of several persistent disks, which we will host on Google Cloud. To create these disks we will create a deployment using Google Cloud Deployment Manager: +```gcloud deployment-manager deployments create wordpress-resources --config wordpress-resources.yaml``` + +where `wordpress-resources.yaml` looks as follows: + +``` +resources: +- name: nfs-disk + type: compute.v1.disk + properties: + zone: us-central1-b + sizeGb: 200 +- name: mysql-disk + type: compute.v1.disk + properties: + zone: us-central1-b + sizeGb: 200 +``` + +### Privileged containers +To use NFS we need to be able to launch privileged containers. Since the release of Kubernetes 1.1 privileged container support is enabled by default. If your Kubernetes cluster doesn't support privileged containers you need to manually change this by setting the flag at `kubernetes/saltbase/pillar/privilege.sls` to true. + +### NFS Library +Mounting NFS volumes requires NFS libraries. Since the release of Kubernetes 1.1 the NFS libraries are installed by default. If they are not installed on your Kubernetes cluster you need to install them manually. + +## Understanding the Wordpress example template +Let's take a closer look at the template used by the Wordpress example. The Wordpress application consists of 4 microservices: an nginx service, a wordpress-php service, a MySQL service, and an NFS service. The architecture looks as follows: + +![Architecture](architecture.png) + +### Variables +The template contains the following variables: + +``` +{% set PROPERTIES = properties or {} %} +{% set PROJECT = PROPERTIES['project'] or 'dm-k8s-testing' %} +{% set NFS_SERVER = PROPERTIES['nfs-server'] or {} %} +{% set NFS_SERVER_IP = NFS_SERVER['ip'] or '10.0.253.247' %} +{% set NFS_SERVER_PORT = NFS_SERVER['port'] or 2049 %} +{% set NFS_SERVER_DISK = NFS_SERVER['disk'] or 'nfs-disk' %} +{% set NFS_SERVER_DISK_FSTYPE = NFS_SERVER['fstype'] or 'ext4' %} +{% set NGINX = PROPERTIES['nginx'] or {} %} +{% set NGINX_PORT = 80 %} +{% set NGINX_REPLICAS = NGINX['replicas'] or 2 %} +{% set WORDPRESS_PHP = PROPERTIES['wordpress-php'] or {} %} +{% set WORDPRESS_PHP_REPLICAS = WORDPRESS_PHP['replicas'] or 2 %} +{% set WORDPRESS_PHP_PORT = WORDPRESS_PHP['port'] or 9000 %} +{% set MYSQL = PROPERTIES['mysql'] or {} %} {% set MYSQL_PORT = MYSQL['port'] or 3306 %} {% set MYSQL_PASSWORD = MYSQL['password'] or 'mysql-password' %} {% set MYSQL_DISK = MYSQL['disk'] or 'mysql-disk' %} {% set MYSQL_DISK_FSTYPE = MYSQL['fstype'] or 'ext4' %} +``` + +### Nginx service +The nginx service is a replicated service with 2 replicas: + +``` +- name: nginx + type: https://raw.githubusercontent.com/kubernetes/deployment-manager/master/templates/replicatedservice/v2/replicatedservice.py + properties: + service_port: {{ NGINX_PORT }} + container_port: {{ NGINX_PORT }} + replicas: {{ NGINX_REPLICAS }} + external_service: true + image: gcr.io/{{ PROJECT }}/nginx:latest + volumes: + - mount_path: /var/www/html + persistentVolumeClaim: + claimName: nfs +``` + +The nginx image builds upon the standard nginx image and simply copies a custom configuration file. + +### Wordpress-php service +The wordpress-php service is a replicated service with 2 replicas: + +``` +- name: wordpress-php + type: https://raw.githubusercontent.com/kubernetes/deployment-manager/master/templates/replicatedservice/v2/replicatedservice.py + properties: + service_name: wordpress-php + service_port: {{ WORDPRESS_PHP_PORT }} + container_port: {{ WORDPRESS_PHP_PORT }} + replicas: 2 + image: wordpress:fpm + env: + - name: WORDPRESS_DB_PASSWORD + value: {{ MYSQL_PASSWORD }} + - name: WORDPRESS_DB_HOST + value: mysql-service + volumes: + - mount_path: /var/www/html + persistentVolumeClaim: + claimName: nfs +``` + +### MySQL service +The MySQL service is a replicated service with a single replica: + +``` +- name: mysql + type: https://raw.githubusercontent.com/kubernetes/deployment-manager/master/templates/replicatedservice/v2/replicatedservice.py + properties: + service_port: {{ MYSQL_PORT }} + container_port: {{ MYSQL_PORT }} + replicas: 1 + image: mysql:5.6 + env: + - name: MYSQL_ROOT_PASSWORD + value: {{ MYSQL_PASSWORD }} + volumes: + - mount_path: /var/lib/mysql + gcePersistentDisk: + pdName: {{ MYSQL_DISK }} + fsType: {{ MYSQL_DISK_FSTYPE }} +``` + +### NFS service +The NFS service is a replicated service with a single replica that is available as a type: + +``` +- name: nfs + type: https://raw.githubusercontent.com/kubernetes/deployment-manager/master/templates/nfs/v1/nfs.jinja + properties: + ip: {{ NFS_SERVER_IP }} + port: {{ NFS_SERVER_PORT }} + disk: {{ NFS_SERVER_DISK }} + fstype: {{NFS_SERVER_DISK_FSTYPE }} +``` + +## Deploying Wordpress +We can now deploy Wordpress using: + +``` +dm deploy examples/wordpress/wordpress.yaml +``` + +where `wordpress.yaml` looks as follows: + +``` +imports: +- path: wordpress.jinja + +resources: +- name: wordpress + type: wordpress.jinja + properties: + project: +``` diff --git a/examples/wordpress/architecture.png b/examples/wordpress/architecture.png new file mode 100644 index 000000000..853039e63 Binary files /dev/null and b/examples/wordpress/architecture.png differ diff --git a/examples/wordpress/images/nginx/Dockerfile b/examples/wordpress/images/nginx/Dockerfile new file mode 100644 index 000000000..ce14e868d --- /dev/null +++ b/examples/wordpress/images/nginx/Dockerfile @@ -0,0 +1,2 @@ +FROM nginx +COPY default.conf /etc/nginx/conf.d/default.conf diff --git a/examples/wordpress/images/nginx/Makefile b/examples/wordpress/images/nginx/Makefile new file mode 100644 index 000000000..3974d978e --- /dev/null +++ b/examples/wordpress/images/nginx/Makefile @@ -0,0 +1,23 @@ +.PHONY: all build push clean + +DOCKER_REGISTRY = gcr.io +PREFIX = $(DOCKER_REGISTRY)/$(PROJECT) +IMAGE = nginx +TAG = latest + +DIR = . + +all: build + +build: + docker build -t $(PREFIX)/$(IMAGE):$(TAG) $(DIR) + +push: build +ifeq ($(DOCKER_REGISTRY),gcr.io) + gcloud docker push $(PREFIX)/$(IMAGE):$(TAG) +else + docker push $(PREFIX)/$(IMAGE):$(TAG) +endif + +clean: + docker rmi $(PREFIX)/$(IMAGE):$(TAG) diff --git a/examples/wordpress/images/nginx/default.conf b/examples/wordpress/images/nginx/default.conf new file mode 100644 index 000000000..af2d7ebf8 --- /dev/null +++ b/examples/wordpress/images/nginx/default.conf @@ -0,0 +1,48 @@ +upstream phpcgi { + server wordpress-php:9000; +} + +server { + listen 80 ; + + root /var/www/html; + index index.php index.html index.htm; + + server_name localhost; + + location / { + try_files $uri $uri/ =404; + } + + location ~ \.php$ { + fastcgi_split_path_info ^(.+\.php)(/.+)$; + # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini + + # With php5-cgi alone: + fastcgi_pass phpcgi; + + # With php5-fpm: + fastcgi_index index.php; + fastcgi_param QUERY_STRING $query_string; + fastcgi_param REQUEST_METHOD $request_method; + fastcgi_param CONTENT_TYPE $content_type; + fastcgi_param CONTENT_LENGTH $content_length; + + fastcgi_param SCRIPT_NAME $fastcgi_script_name; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param REQUEST_URI $request_uri; + fastcgi_param DOCUMENT_URI $document_uri; + fastcgi_param DOCUMENT_ROOT $document_root; + fastcgi_param SERVER_PROTOCOL $server_protocol; + + fastcgi_param GATEWAY_INTERFACE CGI/1.1; + fastcgi_param SERVER_SOFTWARE nginx; + + fastcgi_param REMOTE_ADDR $remote_addr; + fastcgi_param REMOTE_PORT $remote_port; + fastcgi_param SERVER_ADDR $server_addr; + fastcgi_param SERVER_PORT $server_port; + fastcgi_param SERVER_NAME $server_name; + #include fastcgi_params; + } +} diff --git a/examples/wordpress/wordpress-resources.yaml b/examples/wordpress/wordpress-resources.yaml new file mode 100644 index 000000000..00f709de0 --- /dev/null +++ b/examples/wordpress/wordpress-resources.yaml @@ -0,0 +1,12 @@ +# Google Cloud Deployment Manager template +resources: +- name: nfs-disk + type: compute.v1.disk + properties: + zone: us-central1-b + sizeGb: 200 +- name: mysql-disk + type: compute.v1.disk + properties: + zone: us-central1-b + sizeGb: 200 diff --git a/examples/wordpress/wordpress.jinja b/examples/wordpress/wordpress.jinja new file mode 100644 index 000000000..08159e3cb --- /dev/null +++ b/examples/wordpress/wordpress.jinja @@ -0,0 +1,71 @@ +{% set PROPERTIES = properties or {} %} +{% set PROJECT = PROPERTIES['project'] or 'dm-k8s-testing' %} +{% set NFS_SERVER = PROPERTIES['nfs-server'] or {} %} +{% set NFS_SERVER_IP = NFS_SERVER['ip'] or '10.0.253.247' %} +{% set NFS_SERVER_PORT = NFS_SERVER['port'] or 2049 %} +{% set NFS_SERVER_DISK = NFS_SERVER['disk'] or 'nfs-disk' %} +{% set NFS_SERVER_DISK_FSTYPE = NFS_SERVER['fstype'] or 'ext4' %} +{% set NGINX = PROPERTIES['nginx'] or {} %} +{% set NGINX_PORT = 80 %} +{% set NGINX_REPLICAS = NGINX['replicas'] or 2 %} +{% set WORDPRESS_PHP = PROPERTIES['wordpress-php'] or {} %} +{% set WORDPRESS_PHP_REPLICAS = WORDPRESS_PHP['replicas'] or 2 %} +{% set WORDPRESS_PHP_PORT = WORDPRESS_PHP['port'] or 9000 %} +{% set MYSQL = PROPERTIES['mysql'] or {} %} +{% set MYSQL_PORT = MYSQL['port'] or 3306 %} +{% set MYSQL_PASSWORD = MYSQL['password'] or 'mysql-password' %} +{% set MYSQL_DISK = MYSQL['disk'] or 'mysql-disk' %} +{% set MYSQL_DISK_FSTYPE = MYSQL['fstype'] or 'ext4' %} + +resources: +- name: nfs + type: https://raw.githubusercontent.com/kubernetes/deployment-manager/master/templates/nfs/v1/nfs.jinja + properties: + ip: {{ NFS_SERVER_IP }} + port: {{ NFS_SERVER_PORT }} + disk: {{ NFS_SERVER_DISK }} + fstype: {{NFS_SERVER_DISK_FSTYPE }} +- name: nginx + type: https://raw.githubusercontent.com/kubernetes/deployment-manager/master/templates/replicatedservice/v2/replicatedservice.py + properties: + service_port: {{ NGINX_PORT }} + container_port: {{ NGINX_PORT }} + replicas: {{ NGINX_REPLICAS }} + external_service: true + image: gcr.io/{{ PROJECT }}/nginx:latest + volumes: + - mount_path: /var/www/html + persistentVolumeClaim: + claimName: nfs +- name: mysql + type: https://raw.githubusercontent.com/kubernetes/deployment-manager/master/templates/replicatedservice/v2/replicatedservice.py + properties: + service_port: {{ MYSQL_PORT }} + container_port: {{ MYSQL_PORT }} + replicas: 1 + image: mysql:5.6 + env: + - name: MYSQL_ROOT_PASSWORD + value: {{ MYSQL_PASSWORD }} + volumes: + - mount_path: /var/lib/mysql + gcePersistentDisk: + pdName: {{ MYSQL_DISK }} + fsType: {{ MYSQL_DISK_FSTYPE }} +- name: wordpress-php + type: https://raw.githubusercontent.com/kubernetes/deployment-manager/master/templates/replicatedservice/v2/replicatedservice.py + properties: + service_name: wordpress-php + service_port: {{ WORDPRESS_PHP_PORT }} + container_port: {{ WORDPRESS_PHP_PORT }} + replicas: 2 + image: wordpress:fpm + env: + - name: WORDPRESS_DB_PASSWORD + value: {{ MYSQL_PASSWORD }} + - name: WORDPRESS_DB_HOST + value: mysql-service + volumes: + - mount_path: /var/www/html + persistentVolumeClaim: + claimName: nfs diff --git a/examples/wordpress/wordpress.jinja.schema b/examples/wordpress/wordpress.jinja.schema new file mode 100644 index 000000000..215b47e1e --- /dev/null +++ b/examples/wordpress/wordpress.jinja.schema @@ -0,0 +1,69 @@ +info: + title: Wordpress + description: | + Defines a Wordpress website by defining four replicated services: an NFS service, an nginx service, a wordpress-php service, and a MySQL service. + + The nginx service and the Wordpress-php service both use NFS to share files. + +properties: + project: + type: string + default: dm-k8s-testing + description: Project location to load the images from. + nfs-service: + type: object + properties: + ip: + type: string + default: 10.0.253.247 + description: The IP of the NFS service. + port: + type: int + default: 2049 + description: The port of the NFS service. + disk: + type: string + default: nfs-disk + description: The name of the persistent disk the NFS service uses. + fstype: + type: string + default: ext4 + description: The filesystem the disk of the NFS service uses. + nginx: + type: object + properties: + replicas: + type: int + default: 2 + description: The number of replicas for the nginx service. + wordpress-php: + type: object + properties: + replicas: + type: int + default: 2 + description: The number of replicas for the wordpress-php service. + port: + type: int + default: 9000 + description: The port the wordpress-php service runs on. + mysql: + type: object + properties: + port: + type: int + default: 3306 + description: The port the MySQL service runs on. + password: + type: string + default: mysql-password + description: The root password of the MySQL service. + disk: + type: string + default: mysql-disk + description: The name of the persistent disk the MySQL service uses. + fstype: + type: string + default: ext4 + description: The filesystem the disk of the MySQL service uses. + diff --git a/examples/wordpress/wordpress.yaml b/examples/wordpress/wordpress.yaml new file mode 100644 index 000000000..b401897ab --- /dev/null +++ b/examples/wordpress/wordpress.yaml @@ -0,0 +1,6 @@ +imports: +- path: wordpress.jinja + +resources: +- name: wordpress + type: wordpress.jinja diff --git a/manager/manager/types.go b/manager/manager/types.go index 90ca61988..f733b7277 100644 --- a/manager/manager/types.go +++ b/manager/manager/types.go @@ -25,6 +25,9 @@ var Primitives = map[string]bool{ "Service": true, "Namespace": true, "Volume": true, + "Endpoints": true, + "PersistentVolumeClaim": true, + "PersistentVolume": true, } // SchemaImport represents an import as declared in a schema file. diff --git a/templates/nfs/v1/nfs.jinja b/templates/nfs/v1/nfs.jinja new file mode 100644 index 000000000..d8aca3117 --- /dev/null +++ b/templates/nfs/v1/nfs.jinja @@ -0,0 +1,50 @@ +{% set PROPERTIES = properties or {} %} +{% set SERVER_IP = PROPERTIES['ip'] or '10.0.253.247' %} +{% set SERVER_PORT = PROPERTIES['port'] or 2049 %} +{% set SERVER_DISK = PROPERTIES['disk'] or 'nfs-disk' %} +{% set SERVER_DISK_FSTYPE = PROPERTIES['fstype'] or 'ext4' %} +{% set CLAIM_NAME = PROPERTIES['claim-name'] or 'nfs' %} + +resources: +- name: nfs + type: https://raw.githubusercontent.com/leendersr/deployment-manager/master/templates/replicatedservice/v2/replicatedservice.py + properties: + service_port: {{ SERVER_PORT }} + container_port: {{ SERVER_PORT }} + replicas: 1 # Has to be 1 because of the persistent disk + image: gcr.io/google_containers/volume-nfs + privileged: true + cluster_ip: {{ SERVER_IP }} + volumes: + - mount_path: /mnt/data + gcePersistentDisk: + pdName: {{ SERVER_DISK }} + fsType: {{ SERVER_DISK_FSTYPE }} +- name: nfs-pvc + type: PersistentVolumeClaim + properties: + kind: PersistentVolumeClaim + apiVersion: v1 + metadata: + name: {{ CLAIM_NAME }} + spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Mi +- name: nfs-pv + type: PersistentVolume + properties: + apiVersion: v1 + kind: PersistentVolume + metadata: + name: {{ CLAIM_NAME }} + spec: + capacity: + storage: 1Mi + accessModes: + - ReadWriteMany + nfs: + server: {{ SERVER_IP }} + path: "/" diff --git a/templates/nfs/v1/nfs.jinja.schema b/templates/nfs/v1/nfs.jinja.schema new file mode 100644 index 000000000..86d26bb9c --- /dev/null +++ b/templates/nfs/v1/nfs.jinja.schema @@ -0,0 +1,25 @@ +info: + title: NFS + description: Defines an NFS service. + +properties: + ip: + type: string + default: 10.0.253.247 + description: The IP of the NFS service. + port: + type: int + default: 2049 + description: The port of the NFS service. + disk: + type: string + default: nfs-disk + description: The name of the persistent disk the NFS service uses. + fstype: + type: string + default: ext4 + description: The filesystem the disk of the NFS service uses. + claim-name: + type: string + default: nfs + description: The name of the PersistentVolumeClaim diff --git a/templates/nfs/v1/nfs.yaml b/templates/nfs/v1/nfs.yaml new file mode 100644 index 000000000..4d5c68d8a --- /dev/null +++ b/templates/nfs/v1/nfs.yaml @@ -0,0 +1,2 @@ +- name: nfs + type: https://raw.githubusercontent.com/leendersr/deployment-manager/master/templates/nfs/v1/nfs.jinja diff --git a/templates/replicatedservice/v2/replicatedservice.py b/templates/replicatedservice/v2/replicatedservice.py new file mode 100644 index 000000000..a6ef0d71e --- /dev/null +++ b/templates/replicatedservice/v2/replicatedservice.py @@ -0,0 +1,194 @@ +"""Defines a ReplicatedService type by creating both a Service and an RC. + +This module creates a typical abstraction for running a service in a +Kubernetes cluster, namely a replication controller and a service packaged +together into a single unit. +""" + +import yaml + +SERVICE_TYPE_COLLECTION = 'Service' +RC_TYPE_COLLECTION = 'ReplicationController' + + +def GenerateConfig(context): + """Generates a Replication Controller and a matching Service. + + Args: + context: Template context. See schema for context properties + + Returns: + A Container Manifest as a YAML string. + """ + # YAML config that we're going to create for both RC & Service + config = {'resources': []} + + name = context.env['name'] + container_name = context.properties.get('container_name', name) + namespace = context.properties.get('namespace', 'default') + + # Define things that the Service cares about + service_name = context.properties.get('service_name', name + '-service') + service_type = SERVICE_TYPE_COLLECTION + + # Define things that the Replication Controller (rc) cares about + rc_name = context.properties.get('rc_name', name + '-rc') + rc_type = RC_TYPE_COLLECTION + + service = { + 'name': service_name, + 'type': service_type, + 'properties': { + 'apiVersion': 'v1', + 'kind': 'Service', + 'namespace': namespace, + 'metadata': { + 'name': service_name, + 'labels': GenerateLabels(context, service_name), + }, + 'spec': { + 'ports': [GenerateServicePorts(context, container_name)], + 'selector': GenerateLabels(context, name) + } + } + } + set_up_external_lb = context.properties.get('external_service', None) + if set_up_external_lb: + service['properties']['spec']['type'] = 'LoadBalancer' + cluster_ip = context.properties.get('cluster_ip', None) + if cluster_ip: + service['properties']['spec']['clusterIP'] = cluster_ip + config['resources'].append(service) + + rc = { + 'name': rc_name, + 'type': rc_type, + 'properties': { + 'apiVersion': 'v1', + 'kind': 'ReplicationController', + 'namespace': namespace, + 'metadata': { + 'name': rc_name, + 'labels': GenerateLabels(context, rc_name), + }, + 'spec': { + 'replicas': context.properties['replicas'], + 'selector': GenerateLabels(context, name), + 'template': { + 'metadata': { + 'labels': GenerateLabels(context, name), + }, + 'spec': { + 'containers': [ + { + 'env': GenerateEnv(context), + 'name': container_name, + 'image': context.properties['image'], + 'ports': [ + { + 'name': container_name, + 'containerPort': context.properties['container_port'], + } + ], + } + ], + } + } + } + } + } + + # Set up volume mounts + if context.properties.get('volumes', None): + rc['properties']['spec']['template']['spec']['containers'][0]['volumeMounts'] = [] + rc['properties']['spec']['template']['spec']['volumes'] = [] + for volume in context.properties['volumes']: + # mountPath should be unique + volume_name = volume['mount_path'].replace('/', '-').lstrip('-') + '-storage' + rc['properties']['spec']['template']['spec']['containers'][0]['volumeMounts'].append( + { + 'name': volume_name, + 'mountPath': volume['mount_path'] + } + ) + del volume['mount_path'] + volume['name'] = volume_name + rc['properties']['spec']['template']['spec']['volumes'].append(volume) + + if context.properties.get('privileged', False): + rc['properties']['spec']['template']['spec']['containers'][0]['securityContext'] = { + 'privileged': True + } + + config['resources'].append(rc) + return yaml.dump(config) + + +# Generates labels either from the context.properties['labels'] or generates +# a default label 'name':name +def GenerateLabels(context, name): + """Generates labels from context.properties['labels'] or creates default. + + We make a deep copy of the context.properties['labels'] section to avoid + linking in the yaml document, which I believe reduces readability of the + expanded template. If no labels are given, generate a default 'name':name. + + Args: + context: Template context, which can contain the following properties: + labels - Labels to generate + + Returns: + A dict containing labels in a name:value format + """ + tmp_labels = context.properties.get('labels', None) + ret_labels = {'name': name} + if isinstance(tmp_labels, dict): + for key, value in tmp_labels.iteritems(): + ret_labels[key] = value + return ret_labels + + +def GenerateServicePorts(context, name): + """Generates a ports section for a service. + + Args: + context: Template context, which can contain the following properties: + service_port - Port to use for the service + target_port - Target port for the service + protocol - Protocol to use. + + Returns: + A dict containing a port definition + """ + service_port = context.properties.get('service_port', None) + target_port = context.properties.get('target_port', None) + protocol = context.properties.get('protocol') + + ports = {} + if name: + ports['name'] = name + if service_port: + ports['port'] = service_port + if target_port: + ports['targetPort'] = target_port + if protocol: + ports['protocol'] = protocol + + return ports + +def GenerateEnv(context): + """Generates environmental variables for a pod. + + Args: + context: Template context, which can contain the following properties: + env - Environment variables to set. + + Returns: + A list containing env variables in dict format {name: 'name', value: 'value'} + """ + env = [] + tmp_env = context.properties.get('env', []) + for entry in tmp_env: + if isinstance(entry, dict): + env.append({'name': entry.get('name'), 'value': entry.get('value')}) + return env diff --git a/templates/replicatedservice/v2/replicatedservice.py.schema b/templates/replicatedservice/v2/replicatedservice.py.schema new file mode 100644 index 000000000..712ffd315 --- /dev/null +++ b/templates/replicatedservice/v2/replicatedservice.py.schema @@ -0,0 +1,91 @@ +info: + title: Replicated Service + description: | + Defines a ReplicatedService type by creating both a Service and an RC. + + This module creates a typical abstraction for running a service in a + Kubernetes cluster, namely a replication controller and a service packaged + together into a single unit. + +required: +- image + +properties: + container_name: + type: string + description: Name to use for container. If omitted, name is used. + service_name: + type: string + description: Name to use for service. If omitted, name-service is used. + namespace: + type: string + description: Namespace to create resources in. If omitted, 'default' is + used. + default: default + protocol: + type: string + description: Protocol to use for the service. + service_port: + type: int + description: Port to use for the service. + target_port: + type: int + description: Target port to use for the service. + container_port: + type: int + description: Port to use for the container. + replicas: + type: int + description: Number of replicas to create in RC. + image: + type: string + description: Docker image to use for replicas. + labels: + type: object + description: Labels to apply. + env: + type: array + description: Environment variables to apply. + properties: + name: + type: string + value: + type: string + external_service: + type: boolean + description: If set to true, enable external load balancer. + cluster_ip: + type: string + description: IP to use for the service + privileged: + type: boolean + description: If set to true, enable privileged container + volumes: + type: array + description: Volumes to mount. + items: + type: object + properties: + mounth_path: + type: string + description: Path to mount volume + # See https://cloud.google.com/container-engine/docs/spec-schema?hl=en for possible volumes. Since we only use gcePersistentDisk and NFS in our examples we have only added these ones. + oneOf: + gcePersistentDisk: + pdName: + type: string + description: Persistent's disk name + fsType: + type: string + description: Filesystem type of the persistent disk + nfs: + server: + type: string + description: The hostname or IP address of the NFS server + path: + type: string + description: The path that is exported by the NFS server + readOnly: + type: boolean + description: Forces the NFS export to be mounted with read-only permissions +