Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split COS to a generic module #51

Merged
merged 6 commits into from
Mar 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions modules/compute-vm-cos-coredns/cloud-config-file.yaml

This file was deleted.

74 changes: 32 additions & 42 deletions modules/compute-vm-cos-coredns/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,49 +14,9 @@
* limitations under the License.
*/

locals {
files = {
for path, data in var.files :
path => merge(data, {
attributes = (
data.attributes == null
? { owner = "root", permissions = "0644" }
: data.attributes
)
})
}
files_yaml = join("\n", [
for _, data in data.template_file.cloud-config-files : data.rendered
])
}

data "template_file" "cloud-config-files" {
for_each = local.files
template = file("${path.module}/cloud-config-file.yaml")
vars = {
path = each.key
content = each.value.content
owner = each.value.attributes.owner
permissions = each.value.attributes.permissions
}
}

data "template_file" "cloud-config" {
template = file("${path.module}/cloud-config.yaml")
vars = {
corefile = (
var.coredns_corefile == null
? file("${path.module}/Corefile")
: var.coredns_corefile
)
files = local.files_yaml
image = var.coredns_image
log_driver = var.coredns_log_driver
}
}

module "cos-coredns" {
source = "../compute-vm"
source = "../compute-vm-cos"
project_id = var.project_id
region = var.region
zone = var.zone
Expand All @@ -69,12 +29,42 @@ module "cos-coredns" {
metadata = merge(var.metadata, {
google-logging-enabled = var.cos_config.logging
google-monitoring-enabled = var.cos_config.monitoring
user-data = data.template_file.cloud-config.rendered
})
min_cpu_platform = var.min_cpu_platform
network_interfaces = var.network_interfaces
options = var.options
service_account = var.service_account
tags = var.tags
log_driver = var.coredns_log_driver
use_instance_template = var.use_instance_template
cos_config = var.cos_config
image = var.coredns_image
files = {
"/etc/systemd/resolved.conf" : {
content = <<-EOT
[Resolve]
LLMNR=no
DNSStubListener=no
EOT
attributes = null
}
"/etc/coredns/Corefile" : {
content = (var.coredns_corefile == null
? file("${path.module}/Corefile")
: var.coredns_corefile
)
attributes = null
}
}
volumes = {
"/etc/coredns" : "/etc/coredns"
}
pre_runcmds = [
"systemctl restart systemd-resolved.service"
]
extra_args = "-conf /etc/coredns/Corefile"
exposed_ports = {
tcp = [53]
udp = [53]
}
}
101 changes: 101 additions & 0 deletions modules/compute-vm-cos/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Container Optimized OS module

This module allows creating instances (or an instance template) runnning a containerized application using COS. A service account will be created if none is set.

## Example

```hcl
module "nginx" {
source = "./modules/compute-vm-cos"
project_id = var.project_id
region = var.region
zone = var.zone
name = "nginx"
network_interfaces = [{
network = var.vpc_self_link
subnetwork = var.subnet_self_link
nat = false,
addresses = null
}]
cloud_config = {
template_path = "preset:generic.yaml"
variables = {
image = "nginx:1.17"
files = {
"/etc/nginx/htdocs/index.html" : {
content = "hello world"
}
}
exposed_ports = {
tcp = [80]
}
volumes = {
"/etc/nginx/htdocs" : "/usr/share/nginx/html"
}
}
}
}

module "coredns" {
source = "../../tmp/cloud-foundation-fabric/modules/compute-vm-cos/"
project_id = "jccb-testenv"
zone = "europe-west1-b"
region = "europe-west1"
name = "coredns"
network_interfaces = [{
network = "net1"
subnetwork = "https://www.googleapis.com/compute/v1/projects/jccb-testenv/regions/europe-west1/subnetworks/europe-west1"
nat = false,
addresses = null
}]
instance_type = "n1-standard-1"

cloud_config = {
template_path = "preset:coredns.yaml"
variables = {
corefile = "default"
log_driver = "gcplogs"
files = {}
}
}
}

```

<!-- BEGIN TFDOC -->
## Variables

| name | description | type | required | default |
|---|---|:---: |:---:|:---:|
| cloud_config | None | <code title=""></code> | ✓ | |
| name | Instances base name. | <code title="">string</code> | ✓ | |
| network_interfaces | Network interfaces configuration. Use self links for Shared VPC, set addresses to null if not needed. | <code title="list&#40;object&#40;&#123;&#10;nat &#61; bool&#10;network &#61; string&#10;subnetwork &#61; string&#10;addresses &#61; object&#40;&#123;&#10;internal &#61; list&#40;string&#41;&#10;external &#61; list&#40;string&#41;&#10;&#125;&#41;&#10;&#125;&#41;&#41;">list(object({...}))</code> | ✓ | |
| project_id | Project id. | <code title="">string</code> | ✓ | |
| region | Compute region. | <code title="">string</code> | ✓ | |
| zone | Compute zone. | <code title="">string</code> | ✓ | |
| *boot_disk* | Boot disk properties. | <code title="object&#40;&#123;&#10;image &#61; string&#10;size &#61; number&#10;type &#61; string&#10;&#125;&#41;">object({...})</code> | | <code title="&#123;&#10;image &#61; &#34;projects&#47;cos-cloud&#47;global&#47;images&#47;family&#47;cos-stable&#34;&#10;type &#61; &#34;pd-ssd&#34;&#10;size &#61; 10&#10;&#125;">...</code> |
| *cos_config* | Configure COS logging and monitoring. | <code title="object&#40;&#123;&#10;logging &#61; bool&#10;monitoring &#61; bool&#10;&#125;&#41;">object({...})</code> | | <code title="&#123;&#10;logging &#61; false&#10;monitoring &#61; true&#10;&#125;">...</code> |
| *files* | Map of files to create on the instances, path as key. Attributes default to 'root' and '0644', set to null if not needed. | <code title="map&#40;object&#40;&#123;&#10;content &#61; string&#10;attributes &#61; object&#40;&#123;&#10;owner &#61; string&#10;permissions &#61; string&#10;&#125;&#41;&#10;&#125;&#41;&#41;">map(object({...}))</code> | | <code title="">{}</code> |
| *hostname* | Instance FQDN name. | <code title="">string</code> | | <code title="">null</code> |
| *instance_count* | Number of instances to create (only for non-template usage). | <code title="">number</code> | | <code title="">1</code> |
| *instance_type* | Instance type. | <code title="">string</code> | | <code title="">f1-micro</code> |
| *labels* | Instance labels. | <code title="map&#40;string&#41;">map(string)</code> | | <code title="">{}</code> |
| *metadata* | Instance metadata. | <code title="map&#40;string&#41;">map(string)</code> | | <code title="">{}</code> |
| *min_cpu_platform* | Minimum CPU platform. | <code title="">string</code> | | <code title="">null</code> |
| *options* | Instance options. | <code title="object&#40;&#123;&#10;allow_stopping_for_update &#61; bool&#10;can_ip_forward &#61; bool&#10;deletion_protection &#61; bool&#10;preemptible &#61; bool&#10;&#125;&#41;">object({...})</code> | | <code title="&#123;&#10;allow_stopping_for_update &#61; true&#10;can_ip_forward &#61; false&#10;deletion_protection &#61; false&#10;preemptible &#61; false&#10;&#125;">...</code> |
| *service_account* | Service account email (leave empty to auto-create). | <code title="">string</code> | | <code title=""></code> |
| *tags* | Instance tags. | <code title="list&#40;string&#41;">list(string)</code> | | <code title="">["dns", "ssh"]</code> |
| *use_instance_template* | Create instance template instead of instances. | <code title="">bool</code> | | <code title="">false</code> |

## Outputs

| name | description | sensitive |
|---|---|:---:|
| external_ips | Instance main interface external IP addresses. | |
| instances | Instance resources. | |
| internal_ips | Instance main interface internal IP addresses. | |
| names | Instance names. | |
| self_links | Instance self links. | |
| template | Template resource. | |
| template_name | Template name. | |
<!-- END TFDOC -->
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,19 @@ write_files:
LLMNR=no
DNSStubListener=no

# Write coreDNS config
- path: /etc/coredns/Corefile
permissions: 0644
owner: root
content: |
%{ if corefile == "default" ~}
. {
forward . /etc/resolv.conf
log
errors
}
%{ else ~}
${indent(4, corefile)}
%{ endif ~}

# coredns container service
- path: /etc/systemd/system/coredns.service
Expand All @@ -61,14 +68,20 @@ write_files:
ExecStart=/usr/bin/docker run --rm --name=coredns \
--log-driver=${log_driver} --network host \
-v /etc/coredns:/etc/coredns \
${image} -conf /etc/coredns/Corefile
coredns/coredns -conf /etc/coredns/Corefile
ExecStop=/usr/bin/docker stop coredns

${files}
%{ for path, data in files }
- path: ${path}
owner: ${lookup(data, "owner", "root")}
permissions: ${lookup(data, "permissions", "0644")}
content: |
${indent(4, data.content)}
%{ endfor }

runcmd:
- iptables -I INPUT 1 -p tcp -m tcp --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT
- iptables -I INPUT 1 -p udp -m udp --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT
- systemctl daemon-reload
- systemctl restart systemd-resolved.service
- systemctl start coredns
- systemctl start coredns
80 changes: 80 additions & 0 deletions modules/compute-vm-cos/cloud-config/generic.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#cloud-config

# Copyright 2020 Google LLC
#
# 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
#
# https://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.

# TODO: switch to the gcplogs logging driver, and set driver labels

# create a system user, otherwise docker-credential-gcr fails as root
users:
- name: cosuser
uid: 2000
groups: docker

write_files:
- path: /var/lib/docker/daemon.json
permissions: 0644
owner: root
content: |
{
"live-restore": true,
"storage-driver": "overlay2",
"log-opts": {
"max-size": "1024m"
}
}

%{ for path, data in files }
- path: ${path}
owner: ${lookup(data, "owner", "root")}
permissions: ${lookup(data, "permissions", "0644")}
content: |
${indent(4, data.content)}
%{ endfor }

# container service
- path: /etc/systemd/system/cosapp.service
permissions: 0644
owner: root
content: |
[Unit]
Description=Start Application container
After=gcr-online.target docker.socket
Wants=gcr-online.target docker.socket docker-events-collector.service
[Service]
User=cosuser
ExecStartPre=/usr/bin/docker-credential-gcr configure-docker
ExecStart=/usr/bin/docker run --rm --name=cosapp \
--log-driver=${log_driver} --network host \
%{~ for host_path, mount_path in volumes ~}
-v ${host_path}:${mount_path} \
%{~ endfor ~}
${image} ${extra_args}
ExecStop=/usr/bin/docker stop cosapp
ExecStopPost=/usr/bin/docker rm cosapp

runcmd:
- systemctl daemon-reload
%{ for proto, ports in fw_runcmds ~}
%{~ for port in ports ~}
- iptables -I INPUT 1 -p ${proto} -m ${proto} --dport ${port} -m state --state NEW,ESTABLISHED -j ACCEPT
%{~ endfor ~}
%{ endfor ~}
%{ for cmd in pre_runcmds ~}
- ${cmd}
%{ endfor ~}
- systemctl start cosapp
%{ for cmd in pre_runcmds ~}
- ${cmd}
%{ endfor ~}
64 changes: 64 additions & 0 deletions modules/compute-vm-cos/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* Copyright 2020 Google LLC
*
* 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.
*/

locals {
cc = var.cloud_config
ccvars = var.cloud_config.variables

use_generic_template = local.cc.template_path == "preset:generic.yaml"
template_path = replace(local.cc.template_path, "/preset:/", "${path.module}/cloud-config/")

generic_config_vars = {
image = lookup(local.ccvars, "image", "")
extra_args = lookup(local.ccvars, "extra_args", "")
log_driver = lookup(local.ccvars, "log_driver", "gcplogs")
volumes = lookup(local.ccvars, "volumes", {})
pre_runcmds = lookup(local.ccvars, "pre_runcmds", [])
post_runcmds = lookup(local.ccvars, "post_runcmds", [])
fw_runcmds = lookup(local.ccvars, "exposed_ports", [])
files = lookup(local.ccvars, "files", {})
}

cloud_config_content = (
local.use_generic_template
? templatefile(local.template_path, local.generic_config_vars)
: templatefile(local.template_path, var.cloud_config.variables)
)
}

module "vm" {
source = "../compute-vm"
project_id = var.project_id
region = var.region
zone = var.zone
name = var.name
boot_disk = var.boot_disk
hostname = var.hostname
instance_count = var.instance_count
instance_type = var.instance_type
labels = var.labels
metadata = merge(var.metadata, {
google-logging-enabled = var.cos_config.logging
google-monitoring-enabled = var.cos_config.monitoring
user-data = local.cloud_config_content
})
min_cpu_platform = var.min_cpu_platform
network_interfaces = var.network_interfaces
options = var.options
service_account = var.service_account
tags = var.tags
use_instance_template = var.use_instance_template
}
Loading