k8s with kubespray fails at dns config - docker

My k8s with kubespray always bails out at the following error
"Too many nameservers. You can relax this check by set docker_dns_servers_strict=no and we will only use the first 3
In my cluster.yml I have this under - hosts
- docker_dns_servers_strict: no but I still get the error.
What am I missing?

For me, it worked with adding -e 'docker_dns_servers_strict=no':
ansible-playbook -i ../inventories/kubernetes.yaml --become --become-user=root cluster.yml -e 'docker_dns_servers_strict=no'

As explained here, check the format of your yaml file.
Here is one example:
- hosts: k8s-cluster:etcd:calico-rr
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
vars:
- docker_dns_servers_strict: no
roles:
- { role: kubespray-defaults}
- { role: kernel-upgrade, tags: kernel-upgrade, when: kernel_upgrade is defined and kernel_upgrade }
- { role: kubernetes/preinstall, tags: preinstall }
- { role: docker, tags: docker }
- role: rkt
tags: rkt
when: "'rkt' in [etcd_deployment_type, kubelet_deployment_type, vault_deployment_type]"
As mentioned in this issue:
This usually happens if you configure one set of dns servers on the servers before you run the kubespray role.

In my case I added docker_dns_servers_strict: false in the all.yaml file. It's solved my problem.

below worked for my installation by trimming the nameserver to max 6
added it in roles/container-engine/docker/tasks/set_facts_dns.yml
just below trim the nameserver
- name: rtrim number of numbers of search domain to 6
set_fact:
docker_dns_search_domains: "{{ docker_dns_search_domains[0:6] }}"
when: docker_dns_search_domains|length > 6

Related

Using a role per group and assign a host twice to a group

In my environment I have multiple similar hosts and a playbook that uses groups to group roles like icinga, wordpress, gitlab, nginx, generic-php, java, etc. Every role is actually a docker-compose environment which is roles out in a specific location on the server like /srv/docker/<service>/docker-compose.yml. This path is described inside the role.
This services could have multiple instances, one or more per client. Because I don't care about the location (which server to use), it is possible, that a host whould be assigned with a role twice. There could be f.e. the role "wordpress" multiple times. Maybe Wordpress is a bad example, but take generic-php, which hold a HTTP service and executes the index.php in it.
Because the services are roles in Ansible and per role there is a group, like:
- name: Install ReverseProxies
hosts: reverseproxies
roles:
- docker_reverseproxy
An when I have a look into the inventory.yaml like
reverseproxies:
hosts:
server1:
server2:
So I have a problem. How could I assign the group twice to a role. I know about assign a role twice to a host or group, but how would I assign a group twice to a host and define the "differences" like customerId or so? What do I miss? What would be best practice here?
Ideal would be something like this in the inventory (later as JSON in dynamic inventory)
reverseproxies:
hosts:
server1:
customerId: 1
server1:
customerId: 2
server2:
One option would be: change the roles that they verify some host specific variables. So this would be an example playbook:
...
myservice:
hosts:
server1:
service_data:
customer1:
port: 1080
customer2:
port: 1081
server2:
service_data:
customer3:
port: 1080
...
And inside the role iterate over the service_data var
- name: Configure Service instances
include_tasks: manage_service.yml
loop: "{{ service_data | default({}) | dict2items }}"
tags:
- docker
- service
The included tasks then work with item or you could rename it with loop_control and loop_var.
- name: Define location
set_fact:
instance: "{{ item }}"
service_path: "{{ service.base_dir }}/{{ item.key }}"
tags:
- docker
- service
- name: Create "service" directory
file:
path: "{{ service_path }}"
state: directory
tags:
- docker
- service
- name: Copy "service" docker-compose folder
template: src={{template.src}} dest={{template.dest}} owner={{template.owner}} group={{template.group}} mode={{template.mode}}
with_items:
- { src: "docker-compose.yml.j2", dest: "{{ service_path }}/docker-compose.yml", owner: 'root', group: 'root', mode: '0640' }
loop_control:
loop_var: template
tags:
- docker
- service
....
The role should now create directories and so on per customerId list and this should generate unique docker-compose paths with unique and separated environments:
/srv/docker/service/customer1/docker-compose.yml
/srv/docker/service/customer2/docker-compose.yml
/srv/docker/<service>/<customerId>/docker-compose.yml
...

ansible jenkins_plugins mdule : error when playing again a playbook : Jenkins Home not found

I have a problem with the jenkins_plugins module.
Within a playbook that pull a jenkins docker image (jenkins/jenkins:lts-alpine) and runs it to install the instance and configure it, I have a task that installs a list of plugins on an instance, which is :
- name: Install plugins
jenkins_plugin:
owner: "{{ jenkins_process_user }}"
group: "{{ jenkins_process_group }}"
name: "{{ item }}"
state: latest
timeout: 120
url: "http://{{ jenkins_hostname }}:{{ jenkins_http_port }}{{ jenkins_url_prefix }}"
url_username: "{{ jenkins_admin_name }}"
url_password: "{{ jenkins_admin_password }}"
with_dependencies: yes
loop: "{{ jenkinsPlugins }}"
register: pluginResult
until: not pluginResult.failed
retries: 5
notify: restart_image
become: True
become_user: "{{ jenkins_process_user }}"
It works correctly when the playbook is run for the first time.
All plugins are installed, and possibly retried in case of problem.
But, when I relaunch exactly the same playbook, Each and every plugin installation is retried up to the max nbr of retry and fails with (for example):
failed: [devEnv] (item=blueocean) => {"ansible_loop_var": "item", "attempts": 5, "changed": false, "item": "blueocean", "msg": "Jenkins home directory doesn't exist."}
For sure, I have verified that the jenkins home directory actually exists and has the awaited "{{ jenkins_process_user }}" and
"{{ jenkins_process_group }}" owner and group, which is jenkins:jenkins.
Note that the docker container is bound to a local directory which belongs to jenkins:jenkins. To be sure uid and gid are the same on the local machine (a VM created with vagrant) and on the container, the uid:gid are forced to 1001:1001 when starting the container.
I also have checked that it actually the case.
I really cannot explain why I get this error, which clearly makes this playbook not idempotent !
I know that there is a way to install plugins via a shell script provided by Jenkins, but I'd like to stick with ansible playbook as far as possible.
For sure, I can give the whole playbook if you need additional information.
Thanks for your help.
J-L
Ok, I understand the problem.
Reading again the jenkins_plugins documentation, and looking at the jenkins_plugins module code, I found that installation and check already installed plugin version do not run the same code (two different alternatives of a test).
And the second one needs **JENKINS_HOME** to be defined, which is optional (defaults to /var/lib/jenkins) on the module parameters. I did not set it.
Well, it is actually /var/lib/jenkins on the container, but not on the docker controler machine, which is the ansible playbook target where it is /home/jenkins/jenkins_home.
So... This question is closed, unless someone has an additional information to give. You're welcome !
Best Regards.

How to remove outdated containers using ansible?

I'm using with_sequence to iteratively create copies of a container on a single node using ansible. The number of containers is determined by a variable set at the time of deploy. This works well for increasing the number of containers to scale up, but when I reduce the number to deploy less containers the old containers are left running. Is there a way to stop the old containers? Prune won't seem to work correctly since the old containers aren't stopped.
One option is to move from Ansible to docker-compose, which knows how to scale up and scale down (and honestly provides a better use experience for manage complex Docker configurations).
Another idea would be to include one loop for starting containers, and then a second loop that attempts to remove containers up to some maximum number, like this (assuming the number of containers you want to start is in the ansible variable container_count):
---
- hosts: localhost
gather_facts: false
vars:
container_count: 4
maximum_containers: 20
tasks:
- name: Start containers
docker_container:
state: present
name: "service-{{ item }}"
image: fedora
command: "sleep inf"
loop: "{{ range(container_count|int)|list }}"
- name: Stop containers
docker_container:
state: absent
name: "service-{{ item }}"
loop: "{{ range(container_count|int, maximum_containers|int)|list }}"
Called with the default values defined in the playbook, it would create 4 containers and then attempt to delete 16 more. This is going to be a little slow, since Ansible doesn't provide any way to prematurely exit a loop, but it will work.
A third option is to replace the "Stop containers" task with a shell script, which might be slightly faster but less "ansible-like":
---
- hosts: localhost
gather_facts: false
vars:
container_count: 4
tasks:
- name: Start containers
docker_container:
state: present
name: "service-{{ item }}"
image: fedora
command: "sleep inf"
loop: "{{ range(container_count|int)|list }}"
- name: Stop containers
shell: |
let i={{ container_count }}
while :; do
name="service-$i"
docker rm -f $name || break
echo "removed $name"
let i++
done
echo "all done."
Same idea, but somewhat faster and it doesn't require you to define a maximum container count.

ansible: I want to use a group_var when I have a specific JOB_NAME in jenkins

Since JOB_NAME is available as a variable in Jenkins job.
I want a particular variable to be selected when there is certain string in the JOB_NAME variable
so based on different jenkins jobs I can register different variables.
I am trying something as below in group_vars, not sure if it would work.
command: echo "{{ lookup('env','JOB_NAME') }}"
register: jenkins_job_name
when: installation in jenkins_job_name
- topology: topology-02
You may define a list of available topologies somewhere in your group vars and then select one with set_fact depending on JOB_NAME value.
For example:
- hosts: localhost
gather_facts: no
vars:
topologies:
prod: foo
dev: bar
tasks:
- set_fact: topology="{{ topologies[lookup('env','JOB_NAME')] | default('unknown') }}"
- debug: var=topology
This will set:
topology=foo if JOB_NAME=prod
topology=bar if JOB_NAME=dev
topology=unknown otherwise
You may have a complex topology configuration object instead of simple foo/bar strings.

Ansible - Conditionally set volume and tls hostname based on inventory file in docker module

I'm using Ansible to deploy my containers to production. During development, I'd like to have Ansible deploy all containers on my localhost instead of the production servers.
Production servers run on Ubuntu, localhost is OS X with boot2docker.
I have 2 inventory files, production and localhost. My dir structure looks like this:
.
|--inventories
| |localhost
| |production
|
|--group_vars
| |all
| |localhost
| |production
|
|--roles
| |--web
| |--tasks
|main.yml
|
|web.yml
web.yml just defines the host group and assigns the web role.
/roles/web/tasks/main.yml looks like this:
- name: Run web container
docker:
name: web
image: some/image
state: reloaded
...
tls_hostname: boot2docker
volumes:
- "/data/db:/data/db"
env:
...
tags:
- ...
I need to set tls_hostname conditionally, only if the localhost inventory was used; likewise, I want to set the volume only if the production inventory file was used.
Very new to Ansible - it seems like I'm not approaching this to right way there's an easier way to do this? I want to avoid creating completely separate tasks to deploy locally; I just need a way to define volume and tls_hostname conditionally (and leave it at default setting otherwise)
As of Ansible 1.8, you can omit variables and module parameters using the default filter with the special omit value. For example,
- name: Run web container
docker:
name: web
image: some/image
state: reloaded
...
tls_hostname: "{{ hostname | default('some default value') }}"
volumes: "{{ volumes | default(omit) }}"
env:
...
tags:
- ...
I see you do have group_vars files for localhost and production. Are you familiar with that concept? Because I think this is what you're looking for.
The variables defined in the group_vars section will be applied if the host belongs to the respective group.
I need to set tls_hostname conditionally, only if the localhost inventory was used; likewise, I want to set the volume only if the production inventory file was used.
So that sounds like you want to define tls_hostname in ./group_vars/localhost and volume in ./group_vars/production.
(and leave it at default setting otherwise)
Default values can be stored in several places. If you have a role you can store in <role>/defaults/main.yml. group_vars/all also is possible. As well you can set a default value in your yml's.
- name: Run web container
docker:
name: web
image: some/image
state: reloaded
...
tls_hostname: "{{ hostname | default('some default value') }}"
volumes: "{{ volumes | default(['/data/db:/data/db']) }}"
env:
...
tags:
- ...
If hostname or volumes are not defined Ansible will fall back to the defined default value.

Resources