remove dependency on kpm for kubedns
This commit is contained in:
parent
602dba45ea
commit
8b91a43576
5 changed files with 455 additions and 28 deletions
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
kpm_registry: "https://api.kpm.sh"
|
|
||||||
kpm_namespace: "default"
|
|
||||||
kpm_packages: []
|
|
318
roles/kubernetes-apps/library/kube.py
Normal file
318
roles/kubernetes-apps/library/kube.py
Normal file
|
@ -0,0 +1,318 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
DOCUMENTATION = """
|
||||||
|
---
|
||||||
|
module: kube
|
||||||
|
short_description: Manage Kubernetes Cluster
|
||||||
|
description:
|
||||||
|
- Create, replace, remove, and stop resources within a Kubernetes Cluster
|
||||||
|
version_added: "2.0"
|
||||||
|
options:
|
||||||
|
name:
|
||||||
|
required: false
|
||||||
|
default: null
|
||||||
|
description:
|
||||||
|
- The name associated with resource
|
||||||
|
filename:
|
||||||
|
required: false
|
||||||
|
default: null
|
||||||
|
description:
|
||||||
|
- The path and filename of the resource(s) definition file.
|
||||||
|
kubectl:
|
||||||
|
required: false
|
||||||
|
default: null
|
||||||
|
description:
|
||||||
|
- The path to the kubectl bin
|
||||||
|
namespace:
|
||||||
|
required: false
|
||||||
|
default: null
|
||||||
|
description:
|
||||||
|
- The namespace associated with the resource(s)
|
||||||
|
resource:
|
||||||
|
required: false
|
||||||
|
default: null
|
||||||
|
description:
|
||||||
|
- The resource to perform an action on. pods (po), replicationControllers (rc), services (svc)
|
||||||
|
label:
|
||||||
|
required: false
|
||||||
|
default: null
|
||||||
|
description:
|
||||||
|
- The labels used to filter specific resources.
|
||||||
|
server:
|
||||||
|
required: false
|
||||||
|
default: null
|
||||||
|
description:
|
||||||
|
- The url for the API server that commands are executed against.
|
||||||
|
api_version:
|
||||||
|
required: false
|
||||||
|
choices: ['v1', 'v1beta3']
|
||||||
|
default: v1
|
||||||
|
description:
|
||||||
|
- The API version associated with cluster.
|
||||||
|
force:
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
description:
|
||||||
|
- A flag to indicate to force delete, replace, or stop.
|
||||||
|
all:
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
description:
|
||||||
|
- A flag to indicate delete all, stop all, or all namespaces when checking exists.
|
||||||
|
log_level:
|
||||||
|
required: false
|
||||||
|
default: 0
|
||||||
|
description:
|
||||||
|
- Indicates the level of verbosity of logging by kubectl.
|
||||||
|
state:
|
||||||
|
required: false
|
||||||
|
choices: ['present', 'absent', 'latest', 'reloaded', 'stopped']
|
||||||
|
default: present
|
||||||
|
description:
|
||||||
|
- present handles checking existence or creating if definition file provided,
|
||||||
|
absent handles deleting resource(s) based on other options,
|
||||||
|
latest handles creating ore updating based on existence,
|
||||||
|
reloaded handles updating resource(s) definition using definition file,
|
||||||
|
stopped handles stopping resource(s) based on other options.
|
||||||
|
requirements:
|
||||||
|
- kubectl
|
||||||
|
author: "Kenny Jones (@kenjones-cisco)"
|
||||||
|
"""
|
||||||
|
|
||||||
|
EXAMPLES = """
|
||||||
|
- name: test nginx is present
|
||||||
|
kube: name=nginx resource=rc state=present
|
||||||
|
|
||||||
|
- name: test nginx is stopped
|
||||||
|
kube: name=nginx resource=rc state=stopped
|
||||||
|
|
||||||
|
- name: test nginx is absent
|
||||||
|
kube: name=nginx resource=rc state=absent
|
||||||
|
|
||||||
|
- name: test nginx is present
|
||||||
|
kube: filename=/tmp/nginx.yml
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class KubeManager(object):
|
||||||
|
|
||||||
|
def __init__(self, module):
|
||||||
|
|
||||||
|
self.module = module
|
||||||
|
|
||||||
|
self.kubectl = module.params.get('kubectl')
|
||||||
|
if self.kubectl is None:
|
||||||
|
self.kubectl = module.get_bin_path('kubectl', True)
|
||||||
|
self.base_cmd = [self.kubectl]
|
||||||
|
self.api_version = module.params.get('api_version')
|
||||||
|
|
||||||
|
if self.api_version:
|
||||||
|
self.base_cmd.append('--api-version=' + self.api_version)
|
||||||
|
|
||||||
|
if module.params.get('server'):
|
||||||
|
self.base_cmd.append('--server=' + module.params.get('server'))
|
||||||
|
|
||||||
|
if module.params.get('log_level'):
|
||||||
|
self.base_cmd.append('--v=' + str(module.params.get('log_level')))
|
||||||
|
|
||||||
|
if module.params.get('namespace'):
|
||||||
|
self.base_cmd.append('--namespace=' + module.params.get('namespace'))
|
||||||
|
|
||||||
|
self.all = module.params.get('all')
|
||||||
|
self.force = module.params.get('force')
|
||||||
|
self.name = module.params.get('name')
|
||||||
|
self.filename = module.params.get('filename')
|
||||||
|
self.resource = module.params.get('resource')
|
||||||
|
self.label = module.params.get('label')
|
||||||
|
|
||||||
|
def _execute(self, cmd):
|
||||||
|
args = self.base_cmd + cmd
|
||||||
|
try:
|
||||||
|
rc, out, err = self.module.run_command(args)
|
||||||
|
if rc != 0:
|
||||||
|
self.module.fail_json(
|
||||||
|
msg='error running kubectl (%s) command (rc=%d): %s' % (' '.join(args), rc, out or err))
|
||||||
|
except Exception as exc:
|
||||||
|
self.module.fail_json(
|
||||||
|
msg='error running kubectl (%s) command: %s' % (' '.join(args), str(exc)))
|
||||||
|
return out.splitlines()
|
||||||
|
|
||||||
|
def _execute_nofail(self, cmd):
|
||||||
|
args = self.base_cmd + cmd
|
||||||
|
rc, out, err = self.module.run_command(args)
|
||||||
|
if rc != 0:
|
||||||
|
return None
|
||||||
|
return out.splitlines()
|
||||||
|
|
||||||
|
def create(self, check=True):
|
||||||
|
if check and self.exists():
|
||||||
|
return []
|
||||||
|
|
||||||
|
cmd = ['create']
|
||||||
|
|
||||||
|
if not self.filename:
|
||||||
|
self.module.fail_json(msg='filename required to create')
|
||||||
|
|
||||||
|
cmd.append('--filename=' + self.filename)
|
||||||
|
|
||||||
|
return self._execute(cmd)
|
||||||
|
|
||||||
|
def replace(self):
|
||||||
|
|
||||||
|
if not self.force and not self.exists():
|
||||||
|
return []
|
||||||
|
|
||||||
|
cmd = ['replace']
|
||||||
|
if self.api_version != 'v1':
|
||||||
|
cmd = ['update']
|
||||||
|
|
||||||
|
if self.force:
|
||||||
|
cmd.append('--force')
|
||||||
|
|
||||||
|
if not self.filename:
|
||||||
|
self.module.fail_json(msg='filename required to reload')
|
||||||
|
|
||||||
|
cmd.append('--filename=' + self.filename)
|
||||||
|
|
||||||
|
return self._execute(cmd)
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
|
||||||
|
if not self.force and not self.exists():
|
||||||
|
return []
|
||||||
|
|
||||||
|
cmd = ['delete']
|
||||||
|
|
||||||
|
if self.filename:
|
||||||
|
cmd.append('--filename=' + self.filename)
|
||||||
|
else:
|
||||||
|
if not self.resource:
|
||||||
|
self.module.fail_json(msg='resource required to delete without filename')
|
||||||
|
|
||||||
|
cmd.append(self.resource)
|
||||||
|
|
||||||
|
if self.name:
|
||||||
|
cmd.append(self.name)
|
||||||
|
|
||||||
|
if self.label:
|
||||||
|
cmd.append('--selector=' + self.label)
|
||||||
|
|
||||||
|
if self.all:
|
||||||
|
cmd.append('--all')
|
||||||
|
|
||||||
|
if self.force:
|
||||||
|
cmd.append('--ignore-not-found')
|
||||||
|
|
||||||
|
return self._execute(cmd)
|
||||||
|
|
||||||
|
def exists(self):
|
||||||
|
cmd = ['get']
|
||||||
|
|
||||||
|
if not self.resource:
|
||||||
|
return False
|
||||||
|
|
||||||
|
cmd.append(self.resource)
|
||||||
|
|
||||||
|
if self.name:
|
||||||
|
cmd.append(self.name)
|
||||||
|
|
||||||
|
cmd.append('--no-headers')
|
||||||
|
|
||||||
|
if self.label:
|
||||||
|
cmd.append('--selector=' + self.label)
|
||||||
|
|
||||||
|
if self.all:
|
||||||
|
cmd.append('--all-namespaces')
|
||||||
|
|
||||||
|
result = self._execute_nofail(cmd)
|
||||||
|
if not result:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
|
||||||
|
if not self.force and not self.exists():
|
||||||
|
return []
|
||||||
|
|
||||||
|
cmd = ['stop']
|
||||||
|
|
||||||
|
if self.filename:
|
||||||
|
cmd.append('--filename=' + self.filename)
|
||||||
|
else:
|
||||||
|
if not self.resource:
|
||||||
|
self.module.fail_json(msg='resource required to stop without filename')
|
||||||
|
|
||||||
|
cmd.append(self.resource)
|
||||||
|
|
||||||
|
if self.name:
|
||||||
|
cmd.append(self.name)
|
||||||
|
|
||||||
|
if self.label:
|
||||||
|
cmd.append('--selector=' + self.label)
|
||||||
|
|
||||||
|
if self.all:
|
||||||
|
cmd.append('--all')
|
||||||
|
|
||||||
|
if self.force:
|
||||||
|
cmd.append('--ignore-not-found')
|
||||||
|
|
||||||
|
return self._execute(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
|
||||||
|
module = AnsibleModule(
|
||||||
|
argument_spec=dict(
|
||||||
|
name=dict(),
|
||||||
|
filename=dict(),
|
||||||
|
namespace=dict(),
|
||||||
|
resource=dict(),
|
||||||
|
label=dict(),
|
||||||
|
server=dict(),
|
||||||
|
kubectl=dict(),
|
||||||
|
api_version=dict(default='v1', choices=['v1', 'v1beta3']),
|
||||||
|
force=dict(default=False, type='bool'),
|
||||||
|
all=dict(default=False, type='bool'),
|
||||||
|
log_level=dict(default=0, type='int'),
|
||||||
|
state=dict(default='present', choices=['present', 'absent', 'latest', 'reloaded', 'stopped']),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
changed = False
|
||||||
|
|
||||||
|
manager = KubeManager(module)
|
||||||
|
state = module.params.get('state')
|
||||||
|
|
||||||
|
if state == 'present':
|
||||||
|
result = manager.create()
|
||||||
|
|
||||||
|
elif state == 'absent':
|
||||||
|
result = manager.delete()
|
||||||
|
|
||||||
|
elif state == 'reloaded':
|
||||||
|
result = manager.replace()
|
||||||
|
|
||||||
|
elif state == 'stopped':
|
||||||
|
result = manager.stop()
|
||||||
|
|
||||||
|
elif state == 'latest':
|
||||||
|
if manager.exists():
|
||||||
|
manager.force = True
|
||||||
|
result = manager.replace()
|
||||||
|
else:
|
||||||
|
result = manager.create(check=False)
|
||||||
|
|
||||||
|
else:
|
||||||
|
module.fail_json(msg='Unrecognized state %s.' % state)
|
||||||
|
|
||||||
|
if result:
|
||||||
|
changed = True
|
||||||
|
module.exit_json(changed=changed,
|
||||||
|
msg='success: %s' % (' '.join(result))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
from ansible.module_utils.basic import * # noqa
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
|
@ -1,25 +1,19 @@
|
||||||
- name: Install pip
|
---
|
||||||
action:
|
- name: Kubernetes Apps | Lay Down KubeDNS Template
|
||||||
module: "{{ ansible_pkg_mgr }}"
|
template: src={{item.file}} dest=/etc/kubernetes/{{item.file}}
|
||||||
name: "python-pip"
|
with_items:
|
||||||
state: latest
|
- {file: kubedns-rc.yml, type: rc}
|
||||||
when: ansible_os_family != "CoreOS" and kpm_packages | length > 0
|
- {file: kubedns-svc.yml, type: svc}
|
||||||
|
register: manifests
|
||||||
|
when: inventory_hostname == groups['kube-master'][0]
|
||||||
|
|
||||||
- name: install kpm
|
- name: Kubernetes Apps | Start Resources
|
||||||
pip:
|
kube:
|
||||||
name: "kpm"
|
name: KubeDNS
|
||||||
state: "latest"
|
namespace: kube-system
|
||||||
when: kpm_packages | length > 0
|
kubectl: "{{bin_dir}}/kubectl"
|
||||||
|
resource: "{{item.item.type}}"
|
||||||
- name: manage kubernetes applications
|
filename: /etc/kubernetes/{{item.item.file}}
|
||||||
kpm:
|
state: "{{item.changed | ternary('latest','present') }}"
|
||||||
namespace: "{{item.namespace | default(kpm_namespace | default('default'))}}"
|
with_items: "{{ manifests.results }}"
|
||||||
registry: "{{item.registry | default(kpm_registry | default('https://api.kpm.sh'))}}"
|
when: inventory_hostname == groups['kube-master'][0]
|
||||||
state: "{{item.state | default(omit)}}"
|
|
||||||
version: "{{item.version | default(omit)}}"
|
|
||||||
variables: "{{item.variables | default(omit)}}"
|
|
||||||
name: "{{item.name}}"
|
|
||||||
with_items: "{{kpm_packages}}"
|
|
||||||
register: kpmresults
|
|
||||||
environment:
|
|
||||||
PATH: "{{ ansible_env.PATH }}:{{ bin_dir }}"
|
|
||||||
|
|
99
roles/kubernetes-apps/templates/kubedns-rc.yml
Normal file
99
roles/kubernetes-apps/templates/kubedns-rc.yml
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ReplicationController
|
||||||
|
metadata:
|
||||||
|
name: kube-dns-v19
|
||||||
|
namespace: kube-system
|
||||||
|
labels:
|
||||||
|
k8s-app: kube-dns
|
||||||
|
version: v19
|
||||||
|
kubernetes.io/cluster-service: "true"
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
k8s-app: kube-dns
|
||||||
|
version: v19
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
k8s-app: kube-dns
|
||||||
|
version: v19
|
||||||
|
kubernetes.io/cluster-service: "true"
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: kubedns
|
||||||
|
image: gcr.io/google_containers/kubedns-amd64:1.6
|
||||||
|
resources:
|
||||||
|
# TODO: Set memory limits when we've profiled the container for large
|
||||||
|
# clusters, then set request = limit to keep this container in
|
||||||
|
# guaranteed class. Currently, this container falls into the
|
||||||
|
# "burstable" category so the kubelet doesn't backoff from restarting it.
|
||||||
|
limits:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 170Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 70Mi
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 8080
|
||||||
|
scheme: HTTP
|
||||||
|
initialDelaySeconds: 60
|
||||||
|
timeoutSeconds: 5
|
||||||
|
successThreshold: 1
|
||||||
|
failureThreshold: 5
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /readiness
|
||||||
|
port: 8081
|
||||||
|
scheme: HTTP
|
||||||
|
# we poll on pod startup for the Kubernetes master service and
|
||||||
|
# only setup the /readiness HTTP server once that's available.
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
timeoutSeconds: 5
|
||||||
|
args:
|
||||||
|
# command = "/kube-dns"
|
||||||
|
- --domain={{ cluster_name }}.
|
||||||
|
- --dns-port=10053
|
||||||
|
ports:
|
||||||
|
- containerPort: 10053
|
||||||
|
name: dns-local
|
||||||
|
protocol: UDP
|
||||||
|
- containerPort: 10053
|
||||||
|
name: dns-tcp-local
|
||||||
|
protocol: TCP
|
||||||
|
- name: dnsmasq
|
||||||
|
image: gcr.io/google_containers/kube-dnsmasq-amd64:1.3
|
||||||
|
args:
|
||||||
|
- --cache-size=1000
|
||||||
|
- --no-resolv
|
||||||
|
- --server=127.0.0.1#10053
|
||||||
|
ports:
|
||||||
|
- containerPort: 53
|
||||||
|
name: dns
|
||||||
|
protocol: UDP
|
||||||
|
- containerPort: 53
|
||||||
|
name: dns-tcp
|
||||||
|
protocol: TCP
|
||||||
|
- name: healthz
|
||||||
|
image: gcr.io/google_containers/exechealthz-amd64:1.1
|
||||||
|
resources:
|
||||||
|
# keep request = limit to keep this container in guaranteed class
|
||||||
|
limits:
|
||||||
|
cpu: 10m
|
||||||
|
memory: 50Mi
|
||||||
|
requests:
|
||||||
|
cpu: 10m
|
||||||
|
# Note that this container shouldn't really need 50Mi of memory. The
|
||||||
|
# limits are set higher than expected pending investigation on #29688.
|
||||||
|
# The extra memory was stolen from the kubedns container to keep the
|
||||||
|
# net memory requested by the pod constant.
|
||||||
|
memory: 50Mi
|
||||||
|
args:
|
||||||
|
- -cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1 >/dev/null && nslookup kubernetes.default.svc.cluster.local 127.0.0.1:10053 >/dev/null
|
||||||
|
- -port=8080
|
||||||
|
- -quiet
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
protocol: TCP
|
||||||
|
dnsPolicy: Default # Don't use cluster DNS.
|
20
roles/kubernetes-apps/templates/kubedns-svc.yml
Normal file
20
roles/kubernetes-apps/templates/kubedns-svc.yml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: kube-dns
|
||||||
|
namespace: kube-system
|
||||||
|
labels:
|
||||||
|
k8s-app: kube-dns
|
||||||
|
kubernetes.io/cluster-service: "true"
|
||||||
|
kubernetes.io/name: "KubeDNS"
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
k8s-app: kube-dns
|
||||||
|
clusterIP: {{ skydns_server }}
|
||||||
|
ports:
|
||||||
|
- name: dns
|
||||||
|
port: 53
|
||||||
|
protocol: UDP
|
||||||
|
- name: dns-tcp
|
||||||
|
port: 53
|
||||||
|
protocol: TCP
|
Loading…
Reference in a new issue