The official documentation ( https://docs.saltproject.io/en/latest/ref/cache/all/salt.cache.etcd_cache.html#module-salt.cache.etcd_cache ) shows this example config:
etcd.host: 127.0.0.1
etcd.port: 2379
etcd.protocol: http
etcd.allow_reconnect: True
etcd.allow_redirect: False
etcd.srv_domain: None
etcd.read_timeout: 60
etcd.username: None
etcd.password: None
etcd.cert: None
etcd.ca_cert: None
In my particluar case, I have an etcd cluster with PKI (TLS cert based) authentication. The salt module documentation does not say any specific about that use case. It only says this:
Related docs could be found in the python-etcd documentation.
The "related documentation" is in fact very vague here https://python-etcd.readthedocs.io/en/latest/#create-a-client-object - it is not a real documentation, only a list of trivial examples:
import etcd
client = etcd.Client() # this will create a client against etcd server running on localhost on port 4001
client = etcd.Client(port=4002)
client = etcd.Client(host='127.0.0.1', port=4003)
client = etcd.Client(host='127.0.0.1', port=4003, allow_redirect=False) # wont let you run sensitive commands on non-leader machines, default is true
client = etcd.Client(
host='127.0.0.1',
port=4003,
allow_reconnect=True,
protocol='https',)
Of course none of this will work with a proper etcd cluster. However, the source code reveals that it is possible to give a list of hosts:
https://github.com/jplana/python-etcd/blob/master/src/etcd/client.py#L74
Initialize the client.
Args:
host (mixed):
If a string, IP to connect to.
If a tuple ((host, port), (host, port), ...)
But I don't have any idea how to put a tuple of tuples into the salt master config file. This is what I have tried:
cache: etcd
etcd.host: [('salt1.lacinet', 2739), ('salt2.lacinet', 2739)]
etcd.protocol: https
etcd.allow_reconnect: True
etcd.allow_redirect: False
etcd.srv_domain: None
etcd.read_timeout: 60
etcd.username: root
etcd.password: None
etcd.cert: ('/etc/salt/etcd/root.key.pem', '/etc/salt/etcd/root.cert.pem')
etcd.ca_cert: '/etc/salt/etcd/ca.cert.pem'
But it results in an error:
[ERROR ] Could not discover the etcd hosts from None: None of DNS query names exist: _etcd._tcp.None., _etcd._tcp.None.lacinet.
[ERROR ] Failed to get list of machines from https://['salt1.lacinet', 'salt2.lacinet']:2379/v2: LocationParseError("Failed to parse: https://['salt1.lacinet', 'salt2.lacinet']:2379/v2/machines")
[ERROR ] Error in function _pillar:
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/etcd/client.py", line 296, in machines
response = self.http.request(
File "/usr/lib/python3/dist-packages/urllib3/request.py", line 75, in request
return self.request_encode_url(
File "/usr/lib/python3/dist-packages/urllib3/request.py", line 97, in request_encode_url
return self.urlopen(method, url, **extra_kw)
File "/usr/lib/python3/dist-packages/urllib3/poolmanager.py", line 318, in urlopen
u = parse_url(url)
File "/usr/lib/python3/dist-packages/urllib3/util/url.py", line 392, in parse_url
return six.raise_from(LocationParseError(source_url), None)
File "<string>", line 3, in raise_from
urllib3.exceptions.LocationParseError: Failed to parse: https://["('salt1.lacinet'", '2739)', "('salt1.lacinet'", '2739)']:2379/v2/machines
The error itself is very suspicious:
Failed to parse: https://["('salt1.lacinet'", '2739)', "('salt1.lacinet'", '2739)']:2379/v2/machines
I suspect that the host list is not recognized as a list or tuple, but as a string.
Given this error, it might even be possible that salt-master minion cache does not support multiple etcd hosts? But that would be very "interesting", since the main reason of installing etcd is to provide a HA key-value storage for multiple salt masters. What is the point if it can only use a single etcd server?
I'll likely have problems with the TLS cert based authentication as well, because it also uses a tuple (or it should, as given in https://github.com/jplana/python-etcd/blob/master/src/etcd/client.py#L90 ):
cert (mixed): If a string, the whole ssl client certificate;
if a tuple, the cert and key file names.
ca_cert (str): The ca certificate. If pressent it will enable
validation.
It is not clear how to specify a tuple of filenames in the config. Also not clear if the ca_cert configuration is the path of a cert file, or it is the PEM cert string itself. None of this is documented anywhere (or just I could not find it).
Can anybody please tell me howto use a proper TLS-auth etcd cluster with salt-master as the minion cache? Is it possible at all?