Solaris Zones – How to configure

1 09 2008

Title in portuguese (Solaris Zonas – Como configurar).

Zones is the technology that provides a system isolation for Solaris OS that is extremly secure and scalable. It is a virtualized OS Service that allows users to use different instances of Operating System in the same server. It is called lightweight VM because Solaris Zones works a lillte bit different than others Virtualization Products such as VMware. It is important to highlight that Solaris Zones have smallest process overhead because it duplicates only some processes for each zone and not the whole system. If you are familiar with BSD jails, you notice similar concept in Solaris zones.

The idea of Solaris Zone is to create an isolated environment and processes tree. The users will use each zone as an separated server, each one with its processes. Processes inside one Zone can not affect processes in other zones. Users connected to one zone can not affect processes in other zones.

Let’s imagine one scenario that you need to run 3 instances of the same application for different customers. You do not want that the application for customer A affects the application for customer B but you have a server with capacity to run those 3 instances. You do not need to use 3 different servers, you can put those 3 application in the same server using Solaris zones. This technology will delivery you an isolated environment where you can use each zone for each customer like separated servers.

When you install a Solaris 10 you will have a Global Zone and from this main zone you can install additional Non-Global Zones. You can imagine a Non-Global Zone as a separated Operating System with its own hostaname, IP and so on. Users can boot, shutdown or reboot only one zone and it will not affect others zones. Global zone is the responsible to manage Non-Global zones.

Note: Zones + Resource Management = Solaris Container

I will show how to create, configure and boot Non-Global Zones. I believe it will clarify some possible doubts:

Before creating a zone the best idea is to prepare the environment that local zone will be mounted (including filesystem, Network Interface, Processors and so on).

In this tutorial I am assuming a server with 1GB ram and 2 CPU’s and 4 disks.

For example:

  • Mount a filesystem on Global Zone to store the non-global zone. (It is very useful when using Veritas Storage Foundation and HA).

  • Plumb a specific network interface dedicated to a non-global zone when applicable.

  • Create a Resource Pool to assign this to a non-global zone (CPU and so on).

Remind that this is only and example and it should be customized according to the platform/application.

bash-3.00# format

Searching for disks…done

AVAILABLE DISK SELECTIONS:

0. c1t0d0 <DEFAULT cyl 4092 alt 2 hd 128 sec 32>

/pci@0,0/pci15ad,1976@10/sd@0,0

1. c1t1d0 <DEFAULT cyl 1020 alt 2 hd 64 sec 32>

/pci@0,0/pci15ad,1976@10/sd@1,0

2. c1t2d0 <DEFAULT cyl 1020 alt 2 hd 64 sec 32>

/pci@0,0/pci15ad,1976@10/sd@2,0

3. c1t3d0 <DEFAULT cyl 6 alt 2 hd 64 sec 32>

/pci@0,0/pci15ad,1976@10/sd@3,0

I will divide disk utilization according to the following table:

  • 0. c1t0d0 – Will be used for the original instalation (Global Zone)

  • 1. c1t1d0 – Will be used for the Zone1 and will be mounted on /zone1

  • 2. c1t2d0 – Will be used for the Zone2 and will be mounted on /zone2

  • 3. c1t3d0 – Will be used for a filesystem that will be shared by Zone1 and Zone2

Note: Keep in mind that we do not need to specify a dedicate filesystem for a zone, so we will create a non-global zone (Zone3) in the /zone3 directory on / filesystem on Global Zone.

GlobalZone

Disk to mount / filesystem = c1t0d0

Network Interface: e1000g0 (shared by all zones)

IP: 192.168.50.1

CPU: 0 and 1

Note: Global Zone is responsible to all resources in the servers.

Zone1

Path to be installed on Global-Zone = /zone1

Disk used to mount /zone1 = c1t1d0

Network Interface: e1000g0 (shared by all zones)

IP:192.168.50.2

CPU = 0 ( I will assign CPU ID 0 to Zone1)

Zone2

Path to be installed on Global-Zone = /zone2

Disk used to mount /zone1 = c1t2d0

Network Interface: e1000g0 (shared by all zones)

IP:192.168.50.3

CPU = 1 (I will assign CPU ID to Zone2)

Zone3

Path to be installed on Global-Zone = /zone3

Disk used to mount /zone1 = c1t0d0 (In this case I am not using a dedicate disk to install the zone. I will be used a direcoty “/zone3” that is mounted on “/” filesystem on global-zone).

Network Interface: e1000g0 (shared by all zones)

IP:192.168.50.4

CPU = 1 and 0 (I will not specify a zone for this Zone, therefore it will use all CPU’s in the server).

In this point I am assuming that I have on the global zone:

  • Network Inteface Plumbed and Up

  • /zone1 mounted

  • /zone2 mounted

  • /zone3 directory created

Okay, our environment on Global-Zone is ready and we can start. (I showed a simple way to prepare an environment for 3 non-global zones. In this tutorial I will show how to create Zone1).

Before start creating the zones, let’s configure the resource pool (CPU and Memory) to be used by the Zone1. (remember that Zone1 has already its directory “/zone1” that will be used to install the zone ready on global-zone, also the network interface is up).

Okay, the first step to create the resource pool is to have in mind which resources will be assign to this pool. In our case, we will create a “zone1-pool” which will have only one processor from those 2 processors installed in the Global-Zone.

1. Configuring resource pool (If you are not interesting to use resource pool and will use only the zones in the traditional way, please go the nest section.)

Let’s start. You should configure the resource pool in the global-zone. Once it is created you will be able to set this for a specific non-global zone (Solaris 10 you just installed).

Verify if pool daemon is running:

bash-3.00# ps -ef | grep poold
bash-3.00# pooladm
pooladm: couldn’t open pools state file: Facility is not active

Start Pooladm. Use -e option to enable pool facility.

bash-3.00# pooladm -e

Create a file with the following information:

vi zone1pool
create pset zone1-pset ( uint pset.min = 1; uint pset.max = 1 )
create pool zone1-pool
associate pool zone1-pool ( pset zone1-pset )

In this example I created a zone1-pset with only 1 processors.

I created a zone1-pool and associate zone1-pset into this pool.

Update the pooladm configuration with the file zone1pool:

bash-3.00# poolcfg -f zone1pool
poolcfg: cannot load configuration from /etc/pooladm.conf: No such file or director
If this error occurs, use -s opation to save current configuration in memory into the file /etc/pooladm.conf

Go ahead and load again the configuration from the file into pooladm configuration.

bash-3.00# poolcfg -f zone1pool

The file is loaded but we need to turn this active:

bash-3.00# pooladm -c

Check the current configuration on Pooladm:

bash-3.00# pooladm

system default

string system.comment

int system.version 1

boolean system.bind-default true

string system.poold.objectives wt-load

pool zone1-pool

int pool.sys_id 1

boolean pool.active true

boolean pool.default false

int pool.importance 1

string pool.comment

pset zone1-pset

pool pool_default

int pool.sys_id 0

boolean pool.active true

boolean pool.default true

int pool.importance 1

string pool.comment

pset pset_default

pset zone1-pset

int pset.sys_id 1

boolean pset.default false

uint pset.min 1

uint pset.max 1

string pset.units population

uint pset.load 0

uint pset.size 1

string pset.comment

cpu

int cpu.sys_id 0

string cpu.comment

string cpu.status on-line

pset pset_default

int pset.sys_id -1

boolean pset.default true

uint pset.min 1

uint pset.max 65536

string pset.units population

uint pset.load 33

uint pset.size 1

string pset.comment

cpu

int cpu.sys_id 1

string cpu.comment

string cpu.status on-line

Okay, at this point you have the pool resource configured but it is not assigned to any zone yet.

In the next chapter we will create a zone and in chapter 3 I will associate with the resource pool.

2. Configuring a non-global zone

Okay, let’s start listing all the zones configured in the platform

bash-3.00# zoneadm list -cv

ID NAME STATUS PATH BRAND IP

0 global running / native shared

Create the zone using the zonecfg command:

bash-3.00# zonecfg -z zone1

zone1: No such zone configured

Use ‘create’ to begin configuring a new zone.

zonecfg:zone1> create

zonecfg:zone1> set zonepath=/zone1

zonecfg:zone1> set autoboot=false

zonecfg:zone1> add net

zonecfg:zone1:net> set physical=e1000g0

zonecfg:zone1:net> set address=192.168.50.2

zonecfg:zone1:net> end

zonecfg:zone1> verify

zonecfg:zone1> exit

zonepath = Path that the zone will be installed.

Autoboot = if the zone will be booted during the globalzone boot.

Physical = Network Interface that will be used to add an IP for non-global zone. ( you should specify a real interface on Global Zone. It will be added an IP on this interface for a non-global zone.

Address = IP Address that will be assigned for the non-global zone.

List again the zones in the global-zones:

bash-3.00# zoneadm list -cv

ID NAME STATUS PATH BRAND IP

0 global running / native shared

zone1 configured /zone1 native shared

Yeah!!! The zone is configured. It was the first step. You need to perform some more steps in order to get the zone running!!

Here is the list of status that a Zone can be assigned:

  • configured – It has the initial configuration. Zone was not installed and it can not be booted.

  • incomplete – This is the status when zoneadm is installing or unistalling a zone.

  • installed – Zone is configured and packages are installed. You only need to boot it

  • ready – The zone is ready. There is a zsched process and all interfaces are plumbed. It will be moved to running status.

  • Running – It is running!  Everything is ready you can use the zone.

  • Shutting down and down – When the zone is being halted.

Great!! Next step is the installation.

Change the permission for the Zonepath:

bash-3.00# chmod 700 /zone1

Start the installation:

bash-3.00# zoneadm -z zone1 install

Check the status:

bash-3.00# zoneadm list -cv

– zone1 installed /zone1 native shared

ID NAME STATUS PATH BRAND IP

0 global running / native shared

If the status is marked as “installed”, you are ready to boot it!!!

bash-3.00# zoneadm -z zone1 boot

Check the status:

ID NAME STATUS PATH BRAND IP

0 global running / native shared

1 zone1 running /zone1 native shared

It is installed and it is running. The next step is to set the configuration of the OS installed.

To proceed you will need access via CONSOLE.

bash-3.00# zlogin -C zone1

Reply the questions to finish the system configuration step. If you would like to exit the CONSOLE, use “~.”.

Fantastic!!! It is running and you are ready to use your new non-global zone, you can add your application and so on.

Note: Keep in mind that the IP used by non-global zone is added to the interface in the global zone. My sugesstion is to add the IP in the same sub-net as the IP of non-global to the global zone, so you will be able to access it.

That is the ifconfig ouput from the global zone:

lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1

inet 127.0.0.1 netmask ff000000

e1000g0: flags=1004843<UP,BROADCAST,RUNNING,MULTICAST,DHCP,IPv4> mtu 1500 index 2

inet 146.250.176.35 netmask ffffff00 broadcast 146.250.176.255

ether 0:c:29:88:22:71

e1000g0:1: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2

zone zone1

inet 192.168.50.2 netmask ffffff00 broadcast 192.168.50.255

e1000g0:2: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2

inet 192.168.50.1 netmask ffffff00 broadcast 192.168.50.255

lo0: flags=2002000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv6,VIRTUAL> mtu 8252 index 1

inet6 ::1/128

e1000g0: flags=2004841<UP,RUNNING,MULTICAST,DHCP,IPv6> mtu 1500 index 2

inet6 fe80::20c:29ff:fe88:2271/10

ether 0:c:29:88:22:71

Note:

e100g0 is the interface for the traffic network.

e100g0:1 is the interface added by the non-global zone. (zone1)

e100g0:2 is the interface of global zone to access the zones.

Now we can acess this non-global zone via network. (Remind to configure ssh when applicable).

bash-3.00# ssh 192.168.50.2

Password:

Last login: Fri Jul 18 09:05:09 2008 from 192.168.50.1

Sun Microsystems Inc. SunOS 5.10 Generic January 2005

# uname -a

SunOS zone1 5.10 Generic_127128-11 i86pc i386 i86pc

Nice, you are connected into the non-global zone, so, I will show the filesystem configuration.

Use the following command to show the zone configuration:

bash-3.00# zonecfg -z zone1 export

create -b

set zonepath=/zone1

set autoboot=false

set ip-type=shared

add inherit-pkg-dir

set dir=/lib

end

add inherit-pkg-dir

set dir=/platform

end

add inherit-pkg-dir

set dir=/sbin

end

add inherit-pkg-dir

set dir=/usr

end

add net

set address=192.168.50.2

set physical=e1000g0

end

On Solaris Configuration Zone there are two types to configure the filesystem that is the Sparse Root and Whole Root.

Whole Root: Copy all the files required for the system from global-zone.(/usr/ , /lib and so on). The problem on whole root configuration is the space. It requires more space to run the Zones.

Sparse Root: No copy is executed. The main directories are mounted as loop back file system and read-only from the global zone. It helps to save space. That is the most common configuration that I would recommend.

Note in the zone configuration example above that the /usr, /lib, /platform and /sbin are configured on sparse mode (shared with Global Zone). That is the reason it was configured by “inherit-pkg-dir”.

Let’s take a look on the filesystems configured in our non-global zone:

bash-3.00# more /etc/mnttab

/ / ufs rw,intr,largefiles,logging,xattr,onerror=panic,dev=740081 1216324231

/dev /dev lofs zonedevfs,dev=4880003 1216382586

/lib /lib lofs ro,nodevices,nosub,dev=740000 1216382586

/platform /platform lofs ro,nodevices,nosub,dev=740000 1216382586

/sbin /sbin lofs ro,nodevices,nosub,dev=740000 1216382586

/usr /usr lofs ro,nodevices,nosub,dev=740000 1216382586

proc /proc proc nodevices,zone=zone1,dev=4640003 1216382587

ctfs /system/contract ctfs nodevices,zone=zone1,dev=4600004 1216382587

mnttab /etc/mnttab mntfs nodevices,zone=zone1,dev=4680004 1216382587

objfs /system/object objfs nodevices,zone=zone1,dev=4700004 1216382587

swap /etc/svc/volatile tmpfs nodevices,xattr,zone=zone1,dev=46c000a 1216382587

/usr/lib/libc/libc_hwcap1.so.1 /lib/libc.so.1 lofs zone=zone1,dev=740000 1216382589

fd /dev/fd fd rw,nodevices,zone=zone1,dev=48c0004 1216382593

swap /tmp tmpfs nodevices,xattr,zone=zone1,dev=46c000b 1216382593

swap /var/run tmpfs nodevices,xattr,zone=zone1,dev=46c000c 1216382593

-hosts /net autofs nosuid,indirect,ignore,nobrowse,zone=zone1,dev=4980005 1216382602

auto_home /home autofs nodevices,indirect,ignore,nobrowse,zone=zone1,dev=4980006 1216382602

Okay, you can see that /dev, /lib, /platform/, /sbin, /usr are filesystem configured using loop back file system, so it is shared by Global Zone.

The “/” filesystem on non-global zone (zone1) is mounted on the zonepath set during the zone installation. On this case, we defined that the zone1 use the “/zone1” filesystem on global zone as the non-global zone path. In other words, “/” filesystem in non-global zone is the “/zone1” on global zone.

Okay, the next step is to show how to add a new filesystem on global zone to be used on non-global zone as well.

Let’s suppose that /shared is the filesystem on global zone that we will share with non-global zones.

That is the df from global zone:

bash-3.00# uname -a

SunOS solaris-global 5.10 Generic_127128-11 i86pc i386 i86pc

bash-3.00# df -h

Filesystem size used avail capacity Mounted on

/dev/dsk/c1t0d0s0 4.6G 3.1G 1.5G 69% /

/devices 0K 0K 0K 0% /devices

ctfs 0K 0K 0K 0% /system/contract

proc 0K 0K 0K 0% /proc

mnttab 0K 0K 0K 0% /etc/mnttab

swap 647M 692K 647M 1% /etc/svc/volatile

objfs 0K 0K 0K 0% /system/object

/usr/lib/libc/libc_hwcap1.so.1

4.6G 3.1G 1.5G 69% /lib/libc.so.1

fd 0K 0K 0K 0% /dev/fd

swap 647M 548K 647M 1% /tmp

swap 647M 40K 647M 1% /var/run

/dev/dsk/c1t1d0s1 940M 453M 430M 52% /zone1

/dev/dsk/c1t2d0s1 940M 453M 430M 52% /zone2

/dev/dsk/c1t0d0s7 2.7G 2.8M 2.7G 1% /export/home

/dev/dsk/c1t3d0s1 4.0M 1.0M 2.6M 29% /shared

You can see that /shared filesystem is mounted on global zone, now we need to add this to non-global zone:

bash-3.00# zonecfg -z zone1

zonecfg:zone1> add fs

zonecfg:zone1:fs> set dir=/data

zonecfg:zone1:fs> set special=/shared

zonecfg:zone1:fs> set type=lofs

zonecfg:zone1:fs> end

zonecfg:zone1> commit

zonecfg:zone1> exit

bash-3.00# zoneadm -z zone1 reboot

bash-3.00# ssh 192.168.50.2

Password:

Last login: Fri Jul 18 11:40:51 2008 from 192.168.50.1

Sun Microsystems Inc. SunOS 5.10 Generic January 2005

# df -h

Filesystem size used avail capacity Mounted on

/ 940M 453M 430M 52% /

/data 4.0M 1.0M 2.6M 29% /data

/dev 940M 453M 430M 52% /dev

/lib 4.6G 3.1G 1.5G 69% /lib

/platform 4.6G 3.1G 1.5G 69% /platform

/sbin 4.6G 3.1G 1.5G 69% /sbin

/usr 4.6G 3.1G 1.5G 69% /usr

proc 0K 0K 0K 0% /proc

ctfs 0K 0K 0K 0% /system/contract

mnttab 0K 0K 0K 0% /etc/mnttab

objfs 0K 0K 0K 0% /system/object

swap 641M 300K 641M 1% /etc/svc/volatile

/usr/lib/libc/libc_hwcap1.so.1

4.6G 3.1G 1.5G 69% /lib/libc.so.1

fd 0K 0K 0K 0% /dev/fd

swap 641M 68K 641M 1% /tmp

swap 641M 12K 641M 1% /var/run

The first step was adding a new fs in the zone with some properties:

dir – Specify the directory in non-global zone.

Special – Specify the filesystem on global zone that will be used.

Type – Filesystem type. In this case, loop back filesystem (lofs).

After this we need to reboot the zone and connect to check if the filesystem was added to the non-global zone.

3. Setting a resource pool to a zone

In the first section on this article I create a pool zone called “zone1-pool”. The next step is to associate this pool to the zone1.

bash-3.00# zonecfg -z zone1

zonecfg:zone1> set pool=zone1-pool

zonecfg:zone1> verify

zonecfg:zone1> exit

Okay, now the resource pool is associated with the zone. We only need to reboot this.

bash-3.00# zoneadm -z zone1 reboot

Connect to the zone and check if it has only the processor assigned:

bash-3.00# hostname

zone1

bash-3.00# psrset

user processor set 1: processor 0

bash-3.00# psrinfo

0 on-line since 07/17/2008 16:50:08

4. Enabling Fair Share Scheduling on zones.

With FSS, the relative importance of applications is expressed by allocating CPU resources based on shares—a portion of the system’s CPU resources assigned to an application.

In our example, we have already configured the resource pool named zone1-pool and assigned this for zone1.

We also have already installed a second zone (zone2) to proceed with FSS enable example.

The first step we need to set the scheduler for the zone1-pool:

bash-3.00# poolcfg -c ‘modify pool zone1-pool (string pool.scheduler=”FSS”)’

Create a instance of the configuration:

bash-3.00# pooladm -c

Move all the processes in the pool and its associated zones under the FSS.

bash-3.00# priocntl -s -c FSS -i class TS

bash-3.00# priocntl -s -c FSS -i pid 1

Now we need to set zone1-pool into zone2 (We have already set zone1-pool to zone1 before).

bash-3.00# zonecfg -z zone2

zonecfg:zone2> set pool=zone1-pool

zonecfg:zone2> verify

zonecfg:zone2> exit

Now, both zone1 and zone2 are set to use zone1-pool and zone1-pool is assigned to use FSS.

With FSS, the relative importance of applications is expressed by allocating CPU resources based on shares—a portion of the system’s CPU resources assigned to an application. The larger the number of shares assigned to an application, the more CPU resources it receives from the FSS software relative to other applications. The number of shares an application receives is not absolute—what is important is how many shares it has relative to other applications, and whether they will compete with it for CPU resources.

Lets’ assign 3 shares to zone1 and 1 share to zone2.

bash-3.00# zonecfg -z zone1

zonecfg:zone1> add rctl

zonecfg:zone1:rctl> set name=zone.cpu-shares

zonecfg:zone1:rctl> add value (priv=privileged,limit=3,action=none)

zonecfg:zone1:rctl> end

zonecfg:zone1> exit

bash-3.00# zonecfg -z zone2

zonecfg:zone2> add rctl

zonecfg:zone2:rctl> set name=zone.cpu-shares

zonecfg:zone2:rctl> add value (priv=privileged,limit=1,action=none)

zonecfg:zone2:rctl> end

zonecfg:zone2> exit

In this example, we assigned 3 shares to zone1 and 1 share to zone2,then the total number of shares is 1+3 =4. In this example, CPU demand is allocated 75 percent for zone1 and 25 percent for zone2.

Note: Keep in mind that you should have more than one CPU assigned to have a good work of FSS.

According to Sun Manual (System Administrator Guide: Solaris Container-Resource Management and Solaris Zones), if you are using only one CPU the shares you specied are not relevant and each zone will use 50% of CPU. In this example we only provide a quick way to set FSS and Shares.

Tips:

How to monitor CPU usage of projects that run on the system:

bash-3.00# prstat -J

That’s it!Zone1 is fully configured and you can start to use this.

I hope this tutorial helps you to configure your zone.

I took the main steps to create a full zone, you can find great tips @ Sun web site.

If you have any question or comments (would like to add/change something on this article to improve its quality) please contact me.



Actions

Information

One response

9 10 2008
Lani

Hi, your instruction is great, I wish I can practice it but I don’t have 3 disks in one machine. I have a question, IHAC who configured global zone and local zone but when he did ‘ifconfig’ he is not seeing the local IP setup in the global zone. what didn’t he do? I am very new to Sol10 zoning.

Diogo Cortiz Response:

from Diogo Cortiz da Silva
to widodom@hotmail.com
date Tue, Oct 21, 2008 at 2:21 PM
subject Solaris Zones – How to configure
mailed-by gmail.com

hide details 2:21 PM (2 minutes ago)

Reply

Hi,

You sent me one comment at my blog (www.cortiz.org) asking more information about Solaris Zone.

“Hi, your instruction is great, I wish I can practice it but I don’t have 3 disks in one machine. I have a question, IHAC who configured global zone and local zone but when he did ‘ifconfig’ he is not seeing the local IP setup in the global zone. what didn’t he do? I am very new to Sol10 zoning.”

Actually, you do not need 3 disk to configure this scenario. I only describe that you can use 3 zones in different disks, but it is not a requirement, you can only use one disk for as many zones as you want.
According to “ifconfig”, maybe it is not showing the IP for the zone because it is not booted. Can you please issue this command in order to verify that the Local Zone is really running:

“zoneadm list -cv”

Thanks,
Diogo

Leave a comment