简体   繁体   中英

How to install a Python version on server using Ansible

I am using ansible to connect with server. But I am getting errors for certain pip packages because of older version of python. How can I install a specific version of python ( 2.7.10 ) using ansible. Current python version on the server is 2.7.6

For now I have compiled and installed the python version manually but would prefer to have a way to do it via ansible.

Additionally to @Simon Fraser's answer, the following playbook is what I use in Ansible to prepare a server with some specific Python 3 version:

# python_version is a given variable, eg. `3.5`
- name: Check if python is already latest
  command: python3 --version
  register: python_version_result
  failed_when: "{{ python_version_result.stdout | replace('Python ', '') | version_compare(python_version, '>=') }}"

- name: Install prerequisites
  apt: name=python-software-properties state=present
  become: true

- name: Add deadsnakes repo
  apt_repository: repo="ppa:deadsnakes/ppa"
  become: true

- name: Install python
  apt: name="python{{ python_version }}-dev" state=present
  become: true

I have the above in a role too, called ansible-python-latest ( github link ) in case you are interested.

The first thing to consider is that you probably don't want to replace or upgrade the system version of Python. This is because it's used by the system itself for things like package management, and so replacing it may cause other important things to break.

Installing an extra copy of Python that someone else made

To get an extra version of Python installed, the easiest option is to use a ppa , such as https://launchpad.net/~fkrull/+archive/ubuntu/deadsnakes-python2.7 so that someone else has done the work of turning Python into a package for you.

A PPA can be added with Ansible's apt repository module using a directive like the one below, which will then allow you to install packages from it the normal ansible way:

apt_repository: repo='ppa:fkrull/deadsnakes-python2.7'

Building a package yourself

If there is no ppa that has the version of Python you require, then you may need to build a .deb package yourself. The simplest way of doing this is a tool like checkinstall . There's also fpm , which can take lots of different sources and make deb , rpm and so on with them. It can also take a Python module only available with pip install and turn it into a system package for you, which is very useful.

Once you have a deb package you can install it with Ansible's apt module

apt: deb=/tmp/mypackage.deb

I want to point out that there are potentially 2 or 3 different Pythons involved in an Ansible build and that's it's useful not to mix them up.

  • 1️⃣ The system/Ansible Python. On my VirtualBox guest Ubuntu 20.04, that's 3.8.x right now.

  • 2️⃣ Your application/production Python, and that includes what pip/venv are tasked with doing, via Ansible. In my case, my own application code uses 3.10.

  • 3️⃣ The development , not system, Python you use on your host machine, which is again a separate concern. (macos, Python 3.10, in my case).

You want to keep your application's development 3️⃣ and production 2️⃣ Pythons at an equivalent level.

Ansible does not need to use 3.10 however, so I will leave Ansible and system Python alone.

For what it's worth, my host Macbook is running Python 3.10 too, but that does not interfere with the guest's being on 3.8


The following details some of what I did. I don't claim it is best practices, but it does show how I chose to separate those concerns:


ancible.cfg

#dont start out with 3.10, because it may not exist yet
# ansible_python_interpreter=/usr/bin/python3.10
ansible_python_interpreter=/usr/bin/python3 #1️⃣

I did not adjust ansible_python_interpreter throughout my playbook, ie Ansible was left with 20.04's delivered Python.

vars.yml

Track the application Python version in different variables.

# application, not system/Ansible, python
py_appver: "3.10" #2️⃣
py_app_bin: "/usr/bin/python{{py_appver}}"

I very rarely used py_appver in the playbook.

Starting Python state on VM:

(ssha)vagrant bin$pwd
/usr/bin
(ssha)vagrant bin$ls -l python3*
lrwxrwxrwx 1 root root       9 Mar 13  2020 python3 -> python3.8


(ssha)vagrant bin$/usr/bin/python3 --version #1️⃣
Python 3.8.10

playbook.yml:

adding a repository for apt to get 3.10 from:

    - name: add Python dead snakes repo for 3.10
      ansible.builtin.apt_repository:
        repo: 'ppa:deadsnakes/ppa'

Installing Python3.10 and some other packages

    ##############################################
    # These utilities may be used by any of the tasks
    # so might as well put them in early
    ##############################################

    - name: install system-level components
      package: "name={{ item }} state=present"
      with_items:
        - monit
        - runit
....

        # needed by ANXS.postgresql
        - python3-psycopg2


        # not sure I needed but..
        - python3-pip

        #Application Python
        - python{{py_appver}}      #2️⃣
        - python{{py_appver}}-venv #2️⃣

what I did NOT do: symlink python3.10 -> python3

    # DONT DO THIS
    # - name: symlink python executables
    #   file:
    #     src: "/usr/bin/{{item.from_}}{{pyver}}"
    #     dest: "/usr/bin/{{item.to_}}"
    #     state: link
    #     force: true


    #   with_items:        
    #     - {from_: "python", to_: "python3"}
    #     - {from_: "pyvenv-", to_: "pyvenv"}
    #   when: false 

How I used 3.10 for my virtual environment:

Again, this may not necessarily be best practice, but it worked.

The result is to have /srv/venv 4️⃣ virtualenv using Python 3.10

    - name: create virtualenv manually 
      command: "{{py_app_bin}} -m venv ./venv" #2️⃣
      args:
        chdir: "/srv"
      become: yes
      become_user: builder
      when: not venv_exists.stat.exists

And now, I ask pip to self-update and install stuff:

    - name: pip self-update to 20.x
      pip:
        name: pip
        state: latest
        virtualenv: "/srv/venv"  # 4️⃣

    - name: pip requirements 1st pass
      pip:
        requirements: "{{ dir_app }}/requirements.txt"
        virtualenv: "/srv/venv" # 4️⃣
 
        virtualenv_python: "python{{py_appver}}" #2️⃣


And that was it. My pip/venv stuff gets its 3.10 to play with and everything else, including ansible, uses 3.8.

What's in /usr/bin on the VM at the end:

(ssha)vagrant bin$pwd
/usr/bin
(ssha)vagrant bin$ls -l python3*
lrwxrwxrwx 1 root root       9 Mar 13  2020 python3 -> python3.8
-rwxr-xr-x 1 root root 5454104 Dec 21 09:46 python3.10
-rwxr-xr-x 1 root root 5490488 Nov 26 12:14 python3.8
lrwxrwxrwx 1 root root      33 Nov 26 12:14 python3.8-config -> x86_64-linux-gnu-python3.8-config
lrwxrwxrwx 1 root root      16 Mar 13  2020 python3-config -> python3.8-config

(ssha)vagrant bin$python3 --version # 1️⃣
Python 3.8.10

activating the application Python:

(ssha)vagrant bin$source /srv/venv/bin/activate # 4️⃣
(venv) (ssha)vagrant bin$python --version # 2️⃣
Python 3.10.1

Environment

  • host Macos BigSur, Python 3.10
    • vagrant 2.2.19
    • virtualbox 6.1.30,148432
$ansible --version
ansible [core 2.12.1]
  config file = /Users/myuser/.ansible.cfg
  configured module search path = ['/Users/myuser/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /Users/myuser/kds2/venvs/bme/lib/python3.10/site-packages/ansible
  ansible collection location = /Users/myuser/.ansible/collections:/usr/share/ansible/collections
  executable location = /Users/myuser/kds2/venvs/bme/bin/ansible
  python version = 3.10.1 (main, Dec 10 2021, 12:10:01) [Clang 12.0.5 (clang-1205.0.22.11)]
  • guest Ubuntu 20.04 with Python 3.8

Not sure how relevant guest-side ansible is but I'll add it anyway:

$apt list | egrep -i ^ansible

ansible-doc/focal 2.9.6+dfsg-1 all
ansible-lint/focal 4.2.0-1 all
ansible-tower-cli-doc/focal 3.3.0-1.1 all
ansible-tower-cli/focal 3.3.0-1.1 all
ansible/focal 2.9.6+dfsg-1 all

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM